JPP
JPP

Reputation: 460

WPF Master/Detail data binding between 2 combobox

I have two combobox where Parent has to show the list of Countries and the child combo has to show a list of cities of the choosen country. The data is stored in a Dictionary<Int32, List<String>> which has the name CountriesCitiesList. I have the following code

<ComboBox x:Name="cbCountriesList" 
    DataContext="{Binding CountriesCitiesList}"
    IsSynchronizedWithCurrentItem="true">
</ComboBox>

<ComboBox x:Name="cbCitiesList" VirtualizingStackPanel.IsVirtualizing="True"                  
          ItemsSource="{Binding CountriesCitiesList}"
          IsSynchronizedWithCurrentItem="true">
</ComboBox>

The issue is that in the cities combo i can't show the cities list of the country selected. It feel to me that is missing a final step.

Upvotes: 1

Views: 4158

Answers (3)

Stefan PEev
Stefan PEev

Reputation: 491

----------------------------MASTER-------------------------

<ComboBox 
    x:Name="CityCB" 
    ItemsSource="{Binding CitiesList}" 
    DisplayMemberPath="CITYNAME" 
    IsSynchronizedWithCurrentItem="True"/>

----------------------------DETAIL-------------------------

<ComboBox 
    x:Name="RegionCB" 
    ItemsSource="{Binding SelectedItem.REGIONS, ElementName=CityCB}"
    DisplayMemberPath="REGIONNAME" 
    IsSynchronizedWithCurrentItem="True"/>

In this example i'm illustrating master-detail between City and the Regions which it contains.

Upvotes: 0

Rohit Vats
Rohit Vats

Reputation: 81253

If your dictionary CountriesCitiesList contains country Id as Key and List as cities name, you can bind it in pure xaml way something like this -

<ComboBox x:Name="cbCountriesList"
          ItemsSource="{Binding CountriesCitiesList}"
          IsSynchronizedWithCurrentItem="True">
   <ComboBox.ItemTemplate>
      <DataTemplate>
         <TextBlock Text="{Binding Key}"/>
      </DataTemplate>
   </ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="cbCitiesList"
          ItemsSource="{Binding SelectedItem.Value, ElementName=cbCountriesList}"
          IsSynchronizedWithCurrentItem="True"/>

I am assuming you want to show country Id's in cbCountriesList since you are binding it to the dictionary with key of int type.

Upvotes: 7

Metro Smurf
Metro Smurf

Reputation: 38335

For the parent ComboBox, bind the SelectedItem to a property on your model:

<ComboBox x:Name="cbCountriesList" 
    DataContext="{Binding CountriesCitiesList}"
    IsSynchronizedWithCurrentItem="true"
    ItemSource="{Binding}"
    SelectedItem={Binding Path=SomePropertyOnModel} />

Where SomePropertyOnModel is of the same type as an Item in the Countries List.

For the child ComboBox, everything should be the same:

<ComboBox x:Name="cbCitiesList" VirtualizingStackPanel.IsVirtualizing="True"                  
    ItemsSource="{Binding CountriesCitiesList}"
    IsSynchronizedWithCurrentItem ="true"
    ItemSource="{Binding}" />

Side Note: You'll notice that I specifically added the ItemsSource binding to both the ComboBoxes.

In the model, whenever the SomePropertyOnModel is set, update the CountriesCitiesList based on the value received, i.e.,:

private string _somePropertyOnModel;
public string SomePropertyOnModel 
{
    get { return _somePropertyOnModel; }
    set 
    {
        _somePropertyOnModel = value;
        // call NotifyPropertyChanged
        UpdateCountriesCitiesList();
    }
}

private void UpdateCountriesCitiesList()
{
    // set CountriesCitiesList based on the 
    // SomePropertyOnModel value
    // CountriesCitiesList should be an ObservableCollection and the values
    // should be cleared and then added.
    CountriesCitiesList.Clear();
    CountriesCitiesList.Add( "Springfield" );
}

Upvotes: 0

Related Questions