2015-01-14 3 views
1

여기 내 다른 문제와 비슷한 모양의 다른 질문을 찾고 있었지만 아무도 대답이 없습니다. 그래서, 여기에 ...Observable 컬렉션에 사용자 정의 컨트롤에서 바인딩 및 알림 받기

WPF와 MVVM 패턴을 사용하여 C# 응용 프로그램을 개발 중입니다. 나는 종속성 속성을 포함하는 UserControl을 (GroupTree라고합니다)가 :

그래서 정의 형 ChartGroupCollection의
public static DependencyProperty ChartGroupsProperty = DependencyProperty.Register("ChartGroups", typeof(ChartGroupCollection), typeof(GroupTree), 
                 new FrameworkPropertyMetadata() { DefaultValue=new ChartGroupCollection(), PropertyChangedCallback = OnChartGroupsChanged, BindsTwoWayByDefault = true }); 
    public ChartGroupCollection ChartGroups 
    { 
     get { return (ChartGroupCollection)GetValue(ChartGroupsProperty); } 
     set 
     { 
      SetValue(ChartGroupsProperty, value); 
     } 
    } 

    private static void OnChartGroupsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (e.OldValue != e.NewValue) 
     { 
      // Nothing at the moment 
     } 
    } 

그것 :

public class ChartGroupCollection : ObservableCollection<ChartGroup> 
{ 
} 

ChartGroup이 INotifyProperty를 사용하는 속성이 들어 나는 독립적으로 확인했습니다 주 수집을 위해 실행해야하는 모든 변경 이벤트가 올바르게 수행되어야합니다.

제어 사용

MainWindow.Xaml :

<Controls:ChartsControl x:Name="Charts1_1" Tree="{Binding ElementName=Groups, Path=ChartGroups}" /> 

는 내가 일하고자하는 때이다 :

<Controls:GroupTree x:Name="Groups" ChartGroups="{Binding MainGroups}" /> 

을 나는 GroupTree 제어에 ChartGroups 값에 바인딩 다른 제어 할 수 있습니다 GroupTree ChartGroups ChartsControl에 동적으로 변경 사항을 알리고 그에 따라 업데이트하기위한 값 변경. 그러나 지금은 기쁨이 없습니다. ChartsControl을 수동으로 새로 고치면 변경 내용이 표시되므로 데이터가 있습니다. MainGroups 속성에 바인딩을 시도했지만 작동하지 않을 수도 있습니다.하지만 그 중 하나는 아닙니다.

나는 무언가를 분명히 놓친 것 같습니다.하지만 확실하지 않습니다. 어떤 아이디어?

PropertyChanged는 결합 특성에 대해 발생 될 때 불행히도 PropertyChanged 콜백만을 호출

답변

2

은 (따라서 evalutate 바인딩 생김).

CollectionChanged 이벤트는 INotifyCollectionChanged으로 제공됩니다. OnChartGroupsChanged

  1. 등록 해당 이벤트에 대한 그리고 스스로를 처리

  2. : 그래서 당신은 두 가지 옵션이 있습니다 (당신이 핸들을 누설하지 않도록, 예전에 대한 해제를 등록해야합니다!) ItemsControl과 같은 것을 파생시키고 Items 속성을 사용하십시오. 이렇게하면 종속성 속성이 제거되고 ItemsControl에서 변경된 모든 항목을 처리 할 수 ​​있습니다.

가능한 경우 두 번째 것이 좋습니다. 그렇지 않은 경우 CollectionChanged 이벤트를 활용하면 이 아니어야합니다.

3

ObservableCollection은 항목이 추가되거나 제거되는 것처럼 컬렉션에서 발생하는 변경 사항을 수신하고 컬렉션의 개별 항목에서 발생한 변경 사항을 알리지 않습니다.

다음 클래스는 추가되는 항목의 INofityPropertyChanged 이벤트에 자신을 등록하여 ObservableCollection의 기능을 향상시키고 컬렉션 항목의 속성이 변경 될 때 ObservableCollection의 CollectionChanged 이벤트를 발생시킵니다.

끝에 ClearItem을 호출하면 모든 이벤트 핸들러가 해제됩니다.

자세한 내용은 아래 링크에서 확인할 수 있습니다. gunr2171 @

How to Listen to Property Changes of Items of an ObservableCollection

using System.ComponentModel; 
using System.Collections.ObjectModel; 
using System.Collections.Specialized; 
using System.Collections; 

namespace VJCollections 
{ 
    /// <summary> 
    ///  This class adds the ability to refresh the list when any property of 
    ///  the objects changes in the list which implements the INotifyPropertyChanged. 
    /// </summary> 
    /// <typeparam name="T"> 
    public class ItemsChangeObservableCollection<T> : 
      ObservableCollection<T> where T : INotifyPropertyChanged 
    { 
     protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      if (e.Action == NotifyCollectionChangedAction.Add) 
      { 
       RegisterPropertyChanged(e.NewItems); 
      } 
      else if (e.Action == NotifyCollectionChangedAction.Remove) 
      { 
       UnRegisterPropertyChanged(e.OldItems); 
      } 
      else if (e.Action == NotifyCollectionChangedAction.Replace) 
      { 
       UnRegisterPropertyChanged(e.OldItems); 
       RegisterPropertyChanged(e.NewItems); 
      } 

      base.OnCollectionChanged(e); 
     } 

     protected override void ClearItems() 
     { 
      UnRegisterPropertyChanged(this); 
      base.ClearItems(); 
     } 

     private void RegisterPropertyChanged(IList items) 
     { 
      foreach (INotifyPropertyChanged item in items) 
      { 
       if (item != null) 
       { 
        item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged); 
       } 
      } 
     } 

     private void UnRegisterPropertyChanged(IList items) 
     { 
      foreach (INotifyPropertyChanged item in items) 
      { 
       if (item != null) 
       { 
        item.PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged); 
       } 
      } 
     } 

     private void item_PropertyChanged(object sender, PropertyChangedEventArgs e) 
     { 
      base.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
     } 
    } 
} 
+0

- 귀하의 제안에 따라 수정 됨. – VijayKP

+0

이것은 앞으로 유용하게 사용할 수있는 매우 유용한 클래스이지만 불행히도 내 문제를 해결하지는 못합니다. 모든 변경 내용이 제대로 알림을 받더라도 사용자 정의 컨트롤을 통해 컬렉션을 바인딩해도 동적 업데이트가 발생하지 않습니다. 이것이 내가 왜이 문제를 일으키는 지 궁금해하는 이유입니다. –

+0

@RobMarsh - ItemsControl, ListBox, TreeView를 사용하여 위의 사항을 신경 쓰지 않고도 필요한 기능을 무료로 사용하고 있습니다. ObservableCollection을 바인딩하기 위해 어떤 컨트롤을 사용하고 있는지 궁금합니다. – VijayKP

관련 문제