Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding a Dictionary to a WinRT ListBox

I've read a number of posts on binding Dictionary to WPF ListView and ListBox but I can't get equivalent code to work in WinRT.

<Grid Margin="10" Width="1000" VerticalAlignment="Stretch">
        <ListBox Name="StatListView" ItemsSource="{Binding FooDictionary}" >
            <ListBox.ItemTemplate>
                <DataTemplate >
                    <Grid Margin="6">
                        <StackPanel Orientation="Horizontal" >
                            <TextBlock Text="{Binding Key}" Margin="5" />
                            <TextBlock Text="{Binding Value}" Margin="5" />
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>


    public Dictionary<string, string> FooDictionary
    {
        get
        {
            Dictionary<string, string> temp = new Dictionary<string, string>();
            temp.Add("key1", "value1");
            temp.Add("key2", "value2");
            temp.Add("key3", "value3");
            temp.Add("key4", "value4");
            return temp;
        }
    }

What is the proper binding?

like image 428
Bill Shihara Avatar asked Nov 11 '12 12:11

Bill Shihara


1 Answers

The error in the output window is (trimmed to the most useful part):

Error: Cannot get 'Key' value (type 'String') from type 
'System.Runtime.InteropServices.WindowsRuntime.CLRIKeyValuePairImpl`2
[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, 
Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, ....

Internally, WinRT is converting the type to:

System.Runtime.InteropServices.WindowsRuntime.CLRIKeyValuePairImpl<K, V>

If you add to your DataTemplate:

<TextBlock Text="{Binding}" Margin="5" />

You'll see that it emits the above type with String, String.

However, for some reason, it's not being properly handled as expected. If you search for that type on the Internet, you'll see that there's a documented bug for the issue on Connect.

A simple work around would be to place your data in a simple object that is not a KeyValuePair:

List<StringKeyValue> temp = new List<StringKeyValue>();
temp.Add(new StringKeyValue { Key = "key1", Value = "value1" } );
temp.Add(new StringKeyValue { Key = "key2", Value = "value2" });
temp.Add(new StringKeyValue { Key = "key3", Value = "value3" });
temp.Add(new StringKeyValue { Key = "key4", Value = "value4" });

this.DefaultViewModel["FooDictionary"] = temp;

public class StringKeyValue
{
    public string Key { get; set; }
    public string Value { get; set; }
}

As an aside, from a simple test at least, it's not the Dictionary that's causing the issue at all, it's the fact that it's a KeyValuePair object instance that's being converted to the CLRIKeyValuePairImpl type mentioned above. I tried just using a list and adding a KeyValuePair<string, string> instance to a List, and that failed as well.

like image 70
WiredPrairie Avatar answered Sep 19 '22 14:09

WiredPrairie