2014-01-24 77 views
0

我是Silverlight MVVM的新手。 我有一個要求顯示父級子級別中的複選框。 加載頁面時,如果孩子被選中,父母複選框也應該被檢查。Silverlight MVVM:根據子狀態更新父視圖模型查看模型

我創建了一個視圖模型如下

public class TestViewModel : INotifyPropertyChanged 
    { 
    private string name; 
     private string percent; 
     private bool isChecked; 
     internal event EventHandler CheckboxStateChanged = delegate { }; 

     private List<TestViewModel> testViewModel; 

     public List<TestViewModel> TestViewModel1 
     { 
      get { return testViewModel; } 
      set 
      { 
       testViewModel = value; 
       NotifyPropertyChanged("TestViewModel1"); 

      } 
     } 

     public TestViewModel() 
     { 
      //IsChecked = true; 
      //Name = "Hello"; 
      //Percent = "10"; 
     } 

     public bool IsChecked 
     { 
      get { return isChecked; } 
      set 
      { 
       isChecked = value; 
       NotifyPropertyChanged("IsChecked"); 
           CheckboxStateChanged(this, new EventArgs()); 

      } 
     } 


    public event PropertyChangedEventHandler PropertyChanged; 
      protected void NotifyPropertyChanged(string propertyName) 
      { 
       if (PropertyChanged != null) 
       { 
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
       } 
      } 

} 

在我main.xaml.cs我創建了將創建複選框的父子層次遞歸方法。 在點擊子複選框,父複選框得到檢查,因爲我在虛擬機(CheckboxStateChanged)中添加了eventhandler,但在頁面加載時如果選中了子項,父項也會被檢查,我無法做到這一點..Pls幫幫我。

注意我不能讓父母檢查,直到我得到孩子的地位,並且一旦我得到孩子狀態m不知道如何回到父母。

父虛擬機包含同一個虛擬機的列表,兒童(即公開名單TestViewModel1)

回答

1

如果我理解你的問題正確的您正在尋找一種方式,從孩子到其父複選框布布爾河了複選框值。

我已經爲樹視圖做了類似的解決方案。此代碼可行,但如果集合發生更改,則需要進行一些事件分離。

以下是用於運行此解決方案的ViewModel部分的一組類。

public class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class StructureViewModel : ViewModelBase 
{   
    private bool? _isChecked = false; 

    public bool? IsChecked 
    { 
     get { return _isChecked; } 
     set 
     { 
      if (_isChecked != value) 
      { 
       _isChecked = value; 
       RaisePropertyChanged("IsChecked");      
      } 
     } 
    } 

    public string Name { get; set; }   
} 

public class ChildViewModel : StructureViewModel 
{ 

} 

public class ParentViewModel : StructureViewModel 
{ 
    public ParentViewModel() 
    { 
     Children = new List<ChildViewModel>();      
    } 

    public ICollection<ChildViewModel> Children { get; set; } 
} 

public class MainViewModel : ViewModelBase 
{ 
    public MainViewModel() 
    { 
     Parents = new List<ParentViewModel>(); 

     var parent = new ParentViewModel { Name = "Parent" }; 

     parent.Children.Add(new ChildViewModel 
     { 
      Name = "Child1"     
     }); 

     parent.Children.Add(new ChildViewModel 
     { 
      Name = "Child2" 
     }); 

     Parents.Add(parent); 
    } 

    public ICollection<ParentViewModel> Parents { get; set; } 
} 

要顯示此我用下面的標記:

 <TreeView ItemsSource="{Binding Parents}"> 
     <TreeView.ItemTemplate> 
      <HierarchicalDataTemplate ItemsSource="{Binding Children}" > 
       <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Name}"> 
        <i:Interaction.Behaviors> 
         <local:CheckParentBehavior Children="{Binding Children}" /> 
        </i:Interaction.Behaviors> 
       </CheckBox> 

      </HierarchicalDataTemplate> 
     </TreeView.ItemTemplate> 
    </TreeView> 

,修復神奇的複選框是CheckParentBehavior:

public class CheckParentBehavior : Behavior<CheckBox> 
{ 
    public IEnumerable<StructureViewModel> Children 
    { 
     get { return (IEnumerable<StructureViewModel>)GetValue(ChildrenProperty); } 
     set { SetValue(ChildrenProperty, value); } 
    } 

    public static readonly DependencyProperty ChildrenProperty = 
     DependencyProperty.Register("Children", typeof(IEnumerable<StructureViewModel>), typeof(CheckParentBehavior), new PropertyMetadata(OnChildrenChanged)); 

    protected override void OnAttached() 
    { 
     if (Children != null) 
      AssociatedObject.IsChecked = GetCheck(Children); 
    } 

    private static void OnChildrenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (e.NewValue != null) 
     { 
      foreach (var child in e.NewValue as IEnumerable<StructureViewModel>) 
       child.PropertyChanged += (_, args) => OnChildPropertyChanged(d as CheckParentBehavior, args); 
     } 
    } 

    private static void OnChildPropertyChanged(CheckParentBehavior behavior, PropertyChangedEventArgs args) 
    { 
     if (args.PropertyName == "IsChecked") 
      behavior.AssociatedObject.IsChecked = GetCheck(behavior.Children); 
    } 

    public static bool? GetCheck(IEnumerable<StructureViewModel> children) 
    { 
     if (children.All(c => c.IsChecked.GetValueOrDefault())) 
      return true; 
     else if (children.Any(c => c.IsChecked.GetValueOrDefault())) 
      return null; 
     else 
      return false; 
    } 


} 

什麼情況是,它偵聽的PropertyChanged每個孩子的事件,如果它改變了缺陷性質,它會相應地改變父母。

希望您可以使用一些此代碼來解決您的問題。

+0

你可以在ViewModel邏輯中做到這一點,但如果「IsChecked」屬性名稱是可配置的,則上面的Beahvior可以重用。 –