Home > Mobile >  Binding dictionary<string, string[]> string key to combobox and array values to listview
Binding dictionary<string, string[]> string key to combobox and array values to listview

Time:09-10

I have a dictionary<string, string[]>. I've bound the keys to a combobox but I've hit a blocker trying to bind the string array to a listview that will dynamically update depending on what key is selected. I'm able to bind the first array to the listview but I'm not sure what I'm missing to get the view to toggle between keys -

Model -

    public class Person
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }        
    }

ViewModel -

    public class ViewModel
    {
        private Dictionary<Person, string[]> _person;

        public Dictionary<Person, string[]> Persons
        {
            get { return _person; }
            set { _person = value; }
        }

        private int _selectedPersonIndex;
        public int SelectedPersonIndex
        {
            get { return _selectedPersonIndex; }
            set
            {
                _selectedPersonIndex = value;
            }
        }

        public ViewModel()
        {
            Persons = new Dictionary<Person, string[]>();
            Persons.Add(new Person() { Name = "Mark" }, new string[] { "shirt", "pants", "shoes" });
            Persons.Add(new Person() { Name = "Sally" }, new string[] { "blouse", "skirt", "boots", "hat" });
        }        
    }

XAML -


<Window x:Class="MVVM_Combobox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewmodel="clr-namespace:MVVM_Combobox.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <viewmodel:ViewModel x:Key="vm"></viewmodel:ViewModel>
    </Window.Resources>
    <StackPanel Orientation="Vertical" DataContext="{Binding Source={StaticResource vm}}">

        <ComboBox Width="200"
            VerticalAlignment="Center"
            HorizontalAlignment="Center"
            x:Name="cmbTest"
            ItemsSource="{Binding Path=Persons.Keys}"
            SelectedValue="{Binding Path=SelectedPersonIndex}"
            DisplayMemberPath="Name"/>

        <ListView ItemsSource="{Binding Path=Persons.Values/}"   
                    x:Name="myListView">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical"></StackPanel>
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <CheckBox IsChecked="{Binding IsSelected, 
                                    RelativeSource={RelativeSource AncestorType=ListViewItem}}"/>
                        <TextBlock Text="{Binding}" />
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</Window>

by adding

 <ListView ItemsSource="{Binding Path=Persons.Values/}" 

It gets me the array value of the first key even before the key is selected from the combobox

CodePudding user response:

You should bind your ComboBox not to Persons.Keys but rather just to Persons. That means that the the DataType of the DataTemplate is KeyValuePair<Person, string[]>>.

If you just wanted to see the Key value in the ComboxBox, then use the DisplayMemberPath attribute. This tells WPF what element of the selected item to show in the UI. And you will want a View-model property to track the currently selected item. Like this:

<ComboBox ItemsSource="{Binding Persons}" 
          DisplayMemberPath="Key.Name" />

But that's not enough. You also need to see all the items in the string array in your detail view. In that case you need your view model to track the currently selected item. Like this:

<ComboBox ItemsSource="{Binding Persons}" 
          DisplayMemberPath="Key.Name" 
          SelectedItem="{Binding SelectedItem}"/>

The backing view-model property would again be that same KeyValuePair type. Like this:

private KeyValuePair<Person, string[]> _selectedItem;
public KeyValuePair<Person, string[]> SelectedItem
{
    get => _selectedItem;
    set => SetField(ref _selectedItem, value);
}

Then you want your ListView (the detail view) to bind to that array of the currently selected item. Since that item is a KeyValuePair, it needs to bind to the Value, like this.

<ListViewItemsSource="{Binding SelectedItem.Value}"
  • Related