如何在UWP中为集合类型定义`DependencyProperty?

时间:2017-07-26 18:52:27

标签: c# xaml uwp

我正在尝试创建一个从Xaml创建的DependencyObject。 它的DependencyProperty类型List<object>定义如下:

    public List<object> Map
    {
        get { return (List<object>)GetValue(MapProperty); }
        set { SetValue(MapProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Map.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MapProperty =
        DependencyProperty.Register("Map", typeof(List<object>), typeof(MyConverter), new PropertyMetadata(null));

的Xaml:

        <MyConverter x:Key="myConverter">
            <MyConverter.Map>
                <TextPair First="App.Blank" Second ="App.BlankViewModel"/>
            </MyConverter.Map>
        </MyConverter>

我一直在接收Cannot add instance of type 'UwpApp.Xaml.TextPair' to a collection of type 'System.Collections.Generic.List<Object>。 什么可能导致此错误?谢谢。

2 个答案:

答案 0 :(得分:4)

您使用DependencyProperty定义了typeof(List<object>)的类型。这意味着该属性需要这种类型。由于List<object>不是 一个TextPair我们需要更通用。不要使用特殊的通用列表类型,只需使用IList作为类型,并添加new List<object>()作为默认值。这应该可以解决你的问题。

public IList Map
{
    get { return (IList)GetValue(MapProperty); }
    set { SetValue(MapProperty, value); }
}

public static readonly DependencyProperty MapProperty =
    DependencyProperty.Register("Map", typeof(IList),
        typeof(MyConverter), new PropertyMetadata(new List<object>()));

修改 看起来UWP的行为与WPF略有不同。要在UWP中运行此代码,您需要使用通用IList<object>代替IList作为属性类型。

答案 1 :(得分:1)

使用Fruchtzwerg显示的方法,您将获得一个意外的单例:MyCoverter的所有实例之间共享一个List实例。

请参见Collection-Type DependencyProperties in the Microsoft Docs

为避免这种情况,您需要像这样单独设置值

public class MyConverter
{
    public IList Map
    {
        get { return (IList)GetValue(MapProperty); }
        set { SetValue(MapProperty, value); }
    }

    public static readonly DependencyProperty MapProperty =
        DependencyProperty.Register("Map", typeof(IList),
        typeof(MyConverter), new PropertyMetadata(null));

    public MyConverter 
    {
        // SetValue causes DependencyProperty precedence issue so bindings 
        // will not work. 
        // WPF supports SetCurrentValue() which solves this but UWP does not 
        this.SetValue(MapProperty, new List<object>());
    }
}

但是,由于DependencyProperty Value Precedence,这将导致另一个问题:由于使用了具有更高优先级的SetValue,您将不再能够绑定到MapProperty。

因此,最佳和正确的解决方案是使用CreateDefaultValueCallback。您可以按照以下步骤进行操作:

public static readonly DependencyProperty MapProperty =
    DependencyProperty.Register("Map", typeof(IList),
    typeof(MyConverter), PropertyMetadata.Create(
    new CreateDefaultValueCallback(() =>
    {
        return new List<object>();
    }
}));