DependencyProperty getter/setter未被调用
我想创建一个从标准网格派生的自定义控件。 我添加了一个ObservableCollection作为自定义控件的DependencyProperty。但是,它的获取/设置从未达到。我可以在创建与ObservableCollection一起正确使用的DependencyProperty方面有一些指导吗?DependencyProperty getter/setter未被调用
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));
}
我建议不使用的ObservableCollection作为Items
依赖属性的类型。
在这里有一个ObservableCollection(我猜)的原因是在分配属性值时,使UserControl能够附加CollectionChanged
处理程序。但ObservableCollection太具体。
WPF中的方法(例如ItemsControl.ItemsSource)是定义一个非常基本的接口类型(如IEnumerable
),并且当该属性被赋值时,找出值集合是否实现了某些更具体的接口。这里至少应该是INotifyCollectionChanged,但该集合也可能实现ICollectionView和INotifyPropertyChanged。所有这些接口都不是强制性的,这将使您的依赖属性绑定到各种集合,从普通数组开始到复杂的ItemCollection。然后
你OnItemsChanged
属性更改回调应该是这样的:
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
}
太棒了,男人! :-) – zoidbeck 2012-02-03 15:12:41
的WPF绑定机制可以绕过你的标准CLR属性,并直接去依赖属性访问器(GetValue
和SetValue
)。
这就是为什么逻辑不应放在CLR属性内部,而应该放在更改后的处理程序中。
<local:MyGrid>
<local:MyGrid.Items>
<sys:String>First Item</sys:String>
<sys:String>Second Item</sys:String>
</local:MyGrid.Items>
</local:MyGrid>
它实际上是调用得到Items
,然后调用Add
每个元素:
另外,ObservableCollection<string>
将永远不会被因为当你使用集合属性从XAML,像下面的设置。
observablecollection应该在您的viewmodel中,而不是您的控件... – thumbmunkeys 2012-02-03 10:15:31
它已经在我的viewmodel中。但是,我如何将它传递给网格?网格不应该知道如何处理集合吗? – phm 2012-02-03 10:18:07
您可以将依赖项属性定义为IEnumerable,如[ItemsControl.ItemsSource](http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemssource.aspx)。或者发布你的代码,这样有人可能会发现它有什么问题。 – Clemens 2012-02-03 10:27:24