未调用DependencyProperty getter / setter

时间:2012-02-03 10:14:01

标签: wpf grid dependency-properties

我正在尝试创建一个从标准网格派生的自定义控件。 我添加了一个ObservableCollection作为Custom控件的DependencyProperty。但是,永远不会达到它的get / set。我可以在创建与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));

}

2 个答案:

答案 0 :(得分:10)

我建议不要使用ObservableCollection作为Items依赖项属性的类型。

在这里使用ObservableCollection的原因(我猜)是在分配属性值时允许UserControl附加CollectionChanged处理程序。但是ObservableCollection太具体了。

WPF中的方法(例如在ItemsControl.ItemsSource中)是定义一个非常基本的接口类型(如IEnumerable),并且在为属性分配值时,查明值集合是否实现了更多具体接口。这至少是INotifyCollectionChanged,但该集合也可能会实现ICollectionViewINotifyPropertyChanged。所有这些接口都不是强制性的,这将使您的依赖属性能够绑定到各种集合,从普通数组开始直到复杂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
}

答案 1 :(得分:4)

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>

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