Bind to arbitrary Dictionary<,> by using a converter to cast object

烈酒焚心 提交于 2021-02-19 04:15:27

问题


I'm trying to workaround the difficulties in binding to a Dictionary in WinRT Xaml (also referenced here). I want to use a converter to do this rather than having to change all of my view-models or business code to return a List of a custom Key Value class.

This means I need to cast an object to a List<> of some type.

    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<>
    }

I don't know how to do this though. When I mouse over the value in the debugger it still remember its appropriate type (like Dictionary) but I don't know how to make use of this at run time. The main problem is that the Convert function won't know the types of the Keys or Values at compile time because I'm using multiple types of Dictionaries.

What do I need to do to convert something of type object (which is guaranteed to actually be a Dictionary<,>) to some sort of List so that I can bind to it in XAML?


回答1:


A dictionary simply isn't a list; there's no way you can cast it to a List<> of some type. It's an IEnumerable, though, so you can iterate over its KeyValuePairs. Or you can use the values of the dictionary -- or its keys. For example:

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;

Substitute whatever types you're using for string. Or use the non-generic version:

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;



回答2:


I've found a solution which...works, but I don't really like it. I'm not sure if this has any unintended consequences in terms of stability or performance.

DictionaryConverter

Uses a custom class and a List as well as dynamics all over to convert the dictionary.

    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; }
    }

This allows the binding to work, which fortunately for me only needs to be One-Way

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>

So using that converter I can bind any type of Dictionary<,> object in my XAML.



来源:https://stackoverflow.com/questions/35158821/bind-to-arbitrary-dictionary-by-using-a-converter-to-cast-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!