2014-01-24 2 views
0

Silverlight MVVM을 처음 사용했습니다. 부모 하위 계층에 확인란을 표시해야한다는 요구 사항이 하나 있습니다. 하위 항목을 선택한 경우 페이지를로드하는 동안 부모 확인란도 선택되어야합니다.Silverlight MVVM : 하위 상태를 기준으로 상위 뷰 모델 업데이트 뷰 모델

내가 체크 박스의 부모 자식 계층을 생성합니다 재귀 적 방법을 만든 내 main.xaml.cs에서

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)); 
       } 
      } 

} 

아래로 뷰 모델을 만들었습니다. 자식 체크 박스를 클릭하면 해당 VM에 대한 이벤트 핸들러 (CheckboxStateChanged)가 추가되었으므로 상위 체크 박스가 선택됩니다. 그러나 하위 페이지를로드 할 때 페이지로드시 상위 페이지도 체크 표시됩니다. 할 수 없습니다 .Pls 도움.

참고 자녀 상태를 얻을 때까지 부모를 확인할 수 없으며 부모 상태로 돌아갈 수있는 방법이 확실하지 않은 아동 상태가 표시됩니다.

부모 VM은 어린이와 같은 VM의 목록 (즉 공공 목록 TestViewModel1) 내가 올바른 당신이 부모의 체크 박스에 어린이 체크 박스 값을 bouble 할 수있는 방법을 찾고 질문을 이해한다면

답변

1

가 포함되어 있습니다.

나는 나무 전망을위한 유사한 해결책을했다. 이 코드는 작동하지만 콜렉션이 변경되면 이벤트 분리가 필요합니다.

다음은이 솔루션의 ViewModel 부분을 실행하는 데 사용되는 클래스 집합입니다. 체크 박스가 CheckParentBehavior 된 수정

 <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> 

마법 :

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; } 
} 

나는 다음과 같은 마크 업을 사용하여이를 표시하려면

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 각 차일을 듣고 있다는 것입니다 ischecked 속성을 변경하면 그에 따라 부모가 변경됩니다.

이 코드 중 일부를 사용하여 문제를 해결할 수 있기를 바랍니다.

+0

ViewModel 논리에서도이 작업을 수행 할 수 있지만 위의 Beahvior는 "IsChecked"속성 이름을 구성 할 수 있으면 다시 사용할 수 있습니다. –