locked
Binding ComboBox using Dictionary RRS feed

  • Question

  • I am trying to bind a combobox with below XAML and C# code in Windows Store Project. The combobox do not show any items in output. I tried setting DisplayMemberPath SelectedValuePath also and that also do not work. Please help.

    XAML

    <ComboBox x:Name="comboTest" Height="30" Width="300" Margin="85,20,981,578" Grid.Row="1"></ComboBox>

    C#

    Dictionary<string, int> testDictionaryObj = new Dictionary<string, int>();
    testDictionaryObj.Add("One", 1);
    testDictionaryObj.Add("Two", 2);
    comboTest.ItemsSource = testDictionaryObj;

    Output




    • Edited by Ningomba Saturday, September 21, 2013 5:05 PM
    Saturday, September 21, 2013 5:04 PM

Answers

  • Hi Ningomba,

    yes, you're right. If you set DisplayMemberPath to "Key", it should display the Key-Property of the underlying KeyValuePair<string,int>. But WinRT makes a CLRIKeyValuePairImpl-Object behind the scenes. The KeyValuePair<string,int> is just a Language Projection. And this CLRIKeyValuePairImpl doesn't do it in the way we expect, so it doesn't work. This is a known bug and is mentioned here on the connect site: https://connect.microsoft.com/VisualStudio/feedback/details/750518/targetexception-error-in-binding-to-dictionary-string-object

    To work around, you could create your own KeyValuePair-class, e.g. like this:

    public class CustomKeyValuePair<TKey, TValue>
    {
        public TKey Key { get; set; }
        public TValue Value { get; set; }
    }

    And then fill your ComboBox like this:

    Dictionary<string, int> testDictionaryObj = new Dictionary<string, int>();
                testDictionaryObj.Add("One", 1);
                testDictionaryObj.Add("Two", 2);
                comboTest.ItemsSource = testDictionaryObj.Select(kvp => new CustomKeyValuePair<string, int> { Key = kvp.Key, Value = kvp.Value });

    And now you can set DisplayMemberPath to Key or Value:

        <ComboBox DisplayMemberPath="Key" x:Name="comboTest" ...>

    Or even specify a DataTemplate to display both:

        <ComboBox  x:Name="comboTest" Width="200" Height="50">
          <ComboBox.ItemTemplate>
            <DataTemplate>
              <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Key}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Value}"/>
              </StackPanel>
            </DataTemplate>
          </ComboBox.ItemTemplate>
        </ComboBox>


    Thomas Claudius Huber

    "If you can´t make your app run faster, make it at least look & feel extremly fast"

    twitter: @thomasclaudiush
    homepage: www.thomasclaudiushuber.com
    author of: ultimate Windows Store Apps handbook | ultimate WPF handbook | ultimate Silverlight handbook


    • Edited by Thomas Claudius HuberMVP Sunday, September 22, 2013 12:45 PM Made Connect-link clickable
    • Marked as answer by Ningomba Sunday, September 22, 2013 6:15 PM
    Sunday, September 22, 2013 12:44 PM

All replies

  • Hi Ningomba,

    yes, you're right. If you set DisplayMemberPath to "Key", it should display the Key-Property of the underlying KeyValuePair<string,int>. But WinRT makes a CLRIKeyValuePairImpl-Object behind the scenes. The KeyValuePair<string,int> is just a Language Projection. And this CLRIKeyValuePairImpl doesn't do it in the way we expect, so it doesn't work. This is a known bug and is mentioned here on the connect site: https://connect.microsoft.com/VisualStudio/feedback/details/750518/targetexception-error-in-binding-to-dictionary-string-object

    To work around, you could create your own KeyValuePair-class, e.g. like this:

    public class CustomKeyValuePair<TKey, TValue>
    {
        public TKey Key { get; set; }
        public TValue Value { get; set; }
    }

    And then fill your ComboBox like this:

    Dictionary<string, int> testDictionaryObj = new Dictionary<string, int>();
                testDictionaryObj.Add("One", 1);
                testDictionaryObj.Add("Two", 2);
                comboTest.ItemsSource = testDictionaryObj.Select(kvp => new CustomKeyValuePair<string, int> { Key = kvp.Key, Value = kvp.Value });

    And now you can set DisplayMemberPath to Key or Value:

        <ComboBox DisplayMemberPath="Key" x:Name="comboTest" ...>

    Or even specify a DataTemplate to display both:

        <ComboBox  x:Name="comboTest" Width="200" Height="50">
          <ComboBox.ItemTemplate>
            <DataTemplate>
              <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Key}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Value}"/>
              </StackPanel>
            </DataTemplate>
          </ComboBox.ItemTemplate>
        </ComboBox>


    Thomas Claudius Huber

    "If you can´t make your app run faster, make it at least look & feel extremly fast"

    twitter: @thomasclaudiush
    homepage: www.thomasclaudiushuber.com
    author of: ultimate Windows Store Apps handbook | ultimate WPF handbook | ultimate Silverlight handbook


    • Edited by Thomas Claudius HuberMVP Sunday, September 22, 2013 12:45 PM Made Connect-link clickable
    • Marked as answer by Ningomba Sunday, September 22, 2013 6:15 PM
    Sunday, September 22, 2013 12:44 PM
  • Thanks Thomas. This is working.
    Sunday, September 22, 2013 6:15 PM