【问题标题】:Bind to arbitrary Dictionary<,> by using a converter to cast object通过使用转换器强制转换对象绑定到任意 Dictionary<,>
【发布时间】:2016-02-03 03:13:31
【问题描述】:

我正在尝试解决 WinRT Xaml 中的 difficulties in binding to a Dictionary(也称为 here)。我想使用转换器来执行此操作,而不必更改所有视图模型或业务代码以返回自定义键值类的列表。

这意味着我需要将一个对象转换为某种类型的 List。

    public object Convert(object value, Type targetType, object parameter, string temp)
    {
        if(value is IDictionary)
        {
            dynamic v = value;

            foreach (dynamic kvp in v)
            {

            }
        }
        return //some sort of List<>
    }

虽然我不知道该怎么做。当我将鼠标悬停在调试器中的值上时,它仍然记得它的适当类型(如 Dictionary),但我不知道如何在运行时使用它。主要问题是 Convert 函数在编译时不知道 Keys 或 Values 的类型,因为我使用了多种类型的字典。

我需要做些什么来将对象类型(保证实际上是 Dictionary)转换为某种列表,以便我可以在 XAML 中绑定到它?

【问题讨论】:

    标签: c# dictionary reflection casting windows-runtime


    【解决方案1】:

    字典根本不是列表;您无法将其转换为某种类型的List&lt;&gt;。不过,它是一个IEnumerable,因此您可以迭代它的KeyValuePairs。或者您可以使用字典的 values 或它的键。例如:

    IDictionary<string, string> dictionary = value as IDictionary<string, string>;
    if (dictionary != null)
    {
        ICollection<string> keys = dictionary.Keys;
        ICollection<string> values = dictionary.Values;
    
        // Either of those can be bound to a ListView or GridView ItemsSource
        return values;
    }
    
    return null;
    

    用您使用的任何类型替换string。或者使用非通用版本:

    IDictionary dictionary = value as IDictionary;
    if (dictionary != null)
    {
        ICollection keys = dictionary.Keys;
        ICollection values = dictionary.Values;
    
        // Either of those can be bound to a ListView or GridView ItemsSource
        return values;
    }
    
    return null;
    

    【讨论】:

    • “演员”措辞不佳。让我感到困惑的是,该函数不知道键和值的类型是什么。如果我传入 Dictionary 或 Dictionary,我希望它能够工作
    • 您仍然可以使用非通用版本返回未知数的List。如果绑定的集合知道如何处理它们,那么您应该很好。
    • 我现在明白了,感谢您的帮助。唯一的另一个问题是键和值都是相关的。
    【解决方案2】:

    我找到了一个可行的解决方案,但我不太喜欢它。我不确定这是否会对稳定性或性能产生任何意想不到的后果。

    字典转换器

    使用自定义类和列表以及动态转换字典。

        public object Convert(object value, Type targetType, object parameter, string temp)
        {
            List<CustomKeyValue> tempList = new List<CustomKeyValue>();
    
            if(value is IDictionary)
            {
                dynamic v = value;
    
                foreach (dynamic kvp in v)
                {
                    tempList.Add(new CustomKeyValue() { Key = kvp.Key, Value = kvp.Value });
                }
            }
    
            return tempList;
        }
    
        public class CustomKeyValue
        {
            public dynamic Key { get; set; }
            public dynamic Value { get; set; }
        }
    

    这允许绑定工作,幸运的是我只需要单向

    XAML

            <ListView ItemsSource="{Binding MyDictionary, Converter={StaticResource DictionaryConverter}}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Key}"/>
                            <TextBlock Text="  :  "/>
                            <TextBlock Text="{Binding Value}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
    

    因此,使用该转换器,我可以在我的 XAML 中绑定任何类型的 Dictionary 对象。

    【讨论】:

      最近更新 更多