不调用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属性,并直接转到依赖属性访问器( GetValue
和SetValue
)。
这就是为什么逻辑不应该被放置在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
。