不调用DependencyProperty getter / setter

我正尝试创build一个从标准网格派生的自定义控件。 我添加了一个ObservableCollection作为自定义控件的DependencyProperty。 但是,它的get / set是永远不会达到的。 我可以在创build一个与ObservableCollection一起工作的DependencyProperty方面有一些指导吗?

public class MyGrid : Grid { public ObservableCollection<string> Items { get { return (ObservableCollection<string>)GetValue(ItemsProperty); } set { SetValue(ItemsProperty, value); } } public static DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<string>), typeof(MyGrid), new UIPropertyMetadata(null, OnItemsChanged)); } 

我build议不要使用ObservableCollection作为Items依赖Items属性的types。

在这里有一个ObservableCollection的原因(我猜)是当赋值属性值时,使UserControl附加一个CollectionChanged处理程序。 但是ObservableCollection太具体了。

在WPF中的方法(例如在ItemsControl.ItemsSource中 )是定义一个非常基本的接口types(如IEnumerable ),并且当该属性被赋值时,找出值集合是否实现了一些更具体的接口。 这至less会在这里INotifyCollectionChanged ,但集合也可能实现ICollectionView和INotifyPropertyChanged 。 所有这些接口都不是强制的,这将使您的依赖属性绑定到各种集合,从一个普通的数组开始,直到一个复杂的ItemCollection 。

您的OnItemsChanged属性更改callback将看起来像这样:

 private static void OnItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { MyGrid grid = obj as MyGrid; if (grid != null) { var oldCollectionChanged = e.OldValue as INotifyCollectionChanged; var newCollectionChanged = e.NewValue as INotifyCollectionChanged; if (oldCollectionChanged != null) { oldCollectionChanged.CollectionChanged -= grid.OnItemsCollectionChanged; } if (newCollectionChanged != null) { newCollectionChanged.CollectionChanged += grid.OnItemsCollectionChanged; // in addition to adding a CollectionChanged handler // any already existing collection elements should be processed here } } } private void OnItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { // handle collection changes here } 

WPF绑定机制可能绕过您的标准CLR属性,并直接转到依赖属性访问器( GetValueSetValue )。

这就是为什么逻辑不应该被放置在CLR属性中,而是在一个改变的处理程序中。

此外, ObservableCollection<string>永远不会被设置,因为当您使用XAML中的集合属性时,如下所示:

 <local:MyGrid> <local:MyGrid.Items> <sys:String>First Item</sys:String> <sys:String>Second Item</sys:String> </local:MyGrid.Items> </local:MyGrid> 

它实际上是调用get一个Items ,然后为每个元素调用Add