2

我有了ObservableCollection类型的DependencyProperty绑定到一个observableCollection自定义控制:集合依赖属性

<MyControl MyCollectionProperty = {Binding MyObservableCollection} ... 

问题是增加了MyObservableCollection不更新MyCollectionProperty

我需要完全取代MyObservableCollection才能使其工作,例如,

MyObservableCollection = null; 
MyObservableCollection = new ObservableCollection(){...} 

有没有更好的方法来处理这个问题?

编辑:

public ObservableCollection<string> Columns 
    { 
     get { return (ObservableCollection<string>)GetValue(ColumnsProperty); } 
     set { SetValue(ColumnsProperty, value); } 
    } 

    public static readonly DependencyProperty ColumnsProperty = 
     DependencyProperty.Register("Columns", typeof(ObservableCollection<string>), typeof(MyControl), 
            new PropertyMetadata(new ObservableCollection<string>(), OnChanged)); 
+0

你会发布你的依赖属性的定义吗?可能是在那里的东西... – 2013-02-22 01:13:02

+0

是你的“MyControl”监视PropertyChanged或CollectionChanged,并且你监视你的可观察集合中的对象的PropertyChanged? – grantnz 2013-02-22 01:15:04

+0

是的,在定义和处理程序中有一个回调CollectionChanged永远不会被解雇。由于我们正在讨论添加,我没有看到在项目上监听PropertyChanged的位置是相关的。 – user1604008 2013-02-22 01:34:34

回答

5

下面是一个工作示例,可以帮助。

在这个例子中,OnChanged方法立即被调用,当单击Add按钮时,“Changed”被写入控制台。

控制

public class MyControl : Control 
{ 

    public ObservableCollection<string> ExtraColumns 
    { 
     get { return (ObservableCollection<string>)GetValue(ExtraColumnsProperty); } 
     set { SetValue(ExtraColumnsProperty, value); } 
    } 

    public static readonly DependencyProperty ExtraColumnsProperty = 
     DependencyProperty.Register("ExtraColumns", typeof(ObservableCollection<string>), typeof(MyControl), 
            new PropertyMetadata(new ObservableCollection<string>(), OnChanged)); 

    static void OnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     (sender as MyControl).OnChanged(); 

    } 

    void OnChanged() 
    { 
     if (ExtraColumns != null) 
      ExtraColumns.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(ExtraColumns_CollectionChanged); 
    } 

    void ExtraColumns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     Console.WriteLine("Changed");  
    } 
} 

的窗口

<Window x:Class="WpfApplication18.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication18" 
    Title="MainWindow" Height="350" Width="525"> 
    <StackPanel> 
    <local:MyControl ExtraColumns="{Binding Extras}"/> 
    <Button Click="Button_Click">Add</Button> 
    </StackPanel> 
</Window> 

窗口代码隐藏

public partial class MainWindow : Window 
{ 
    private ObservableCollection<string> _extras = new ObservableCollection<string>(); 
    public ObservableCollection<string> Extras 
    { 
     get { return _extras; } 
     set 
     { 
      if (value != _extras) 
      { 
       _extras = value; 
      } 
     } 
    } 


    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = this; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Extras.Add("Additional"); 
    } 
} 
+4

你不应该使用代码'new PropertyMetadata(new ObservableCollection ()'在注册依赖属性。请参阅[这里](https://msdn.microsoft.com/en-us/library/vstudio/aa970563%28v=vs.100%29.aspx)的解释 – ghord 2015-06-26 15:24:19

11

除了什么grantz已经回答了,我建议用IEnumerable<string>类型申报财产并在运行时检查集合对象是否实现了INotifyCollectionChanged接口。这提供了更大的灵活性,可以将哪个具体收集实现用作属性值。用户可能决定拥有自己的可观察集合的专门实现。

还要注意的是,在ColumnsPropertyChanged回调中,CollectionChanged事件处理程序附加到新集合,但也从旧集合中删除。

public static readonly DependencyProperty ColumnsProperty = 
    DependencyProperty.Register(
     "Columns", typeof(IEnumerable<string>), typeof(MyControl), 
     new PropertyMetadata(null, ColumnsPropertyChanged)); 

public IEnumerable<string> Columns 
{ 
    get { return (IEnumerable<string>)GetValue(ColumnsProperty); } 
    set { SetValue(ColumnsProperty, value); } 
} 

private static void ColumnsPropertyChanged(
    DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    var control= (MyControl)obj; 
    var oldCollection = e.OldValue as INotifyCollectionChanged; 
    var newCollection = e.NewValue as INotifyCollectionChanged; 

    if (oldCollection != null) 
    { 
     oldCollection.CollectionChanged -= control.ColumnsCollectionChanged; 
    } 

    if (newCollection != null) 
    { 
     newCollection.CollectionChanged += control.ColumnsCollectionChanged; 
    } 

    control.UpdateColumns(); 
} 

private void ColumnsCollectionChanged(
    object sender, NotifyCollectionChangedEventArgs e) 
{ 
    // optionally take e.Action into account 
    UpdateColumns(); 
} 

private void UpdateColumns() 
{ 
    ... 
}