简体   繁体   中英

Bind a WPF ComboBox Based on Data From Another ComboBox Using JSON in C#

I have two comboboxes, one displays the country data, while the second displays cities.

I am binding these combobox using deserialized data from a JSON file structured this way:

 [ { "country": "Albania", "city": [ "Elbasan", "Petran", "Pogradec", "Shkoder", "Tirana", "Ura Vajgurore" ] } ]

Deserializing it and extracting the data like this:

public partial class SomeUCClass: UserControl
{      
    readonly UtilityMethods utilityMethods = new UtilityMethods();

    private string jsonFilePath = @"C:\SomePath\CountryData.json";

    public ObservableCollection<AllCountriesData> countryCityData { get; set; }

    public SomeUCClass()
    {
        InitializeComponent();
        countryCityData = new ObservableCollection<AllCountriesData>();
        DataContext = this;
    }

    private void SomeUCClass_Loaded(object sender, RoutedEventArgs e)
    {
        try
        {
            using (StreamReader streamReader = new StreamReader(jsonFilePath))
            {
                string actualJsonFile = streamReader.ReadToEnd();
                var x = JsonConvert.DeserializeObject<List<AllCountriesData>>(actualJsonFile);
                foreach (var countryCityDataObject in x)
                {
                    countryCityData.Add(new AllCountriesData() { Country = countryCityDataObject.Country, Cities = new ObservableCollection<string>() { countryCityDataObject.MyString.ToString() } });
                }

            }
        }
        catch (Exception ex)
        {
            utilityMethods.ErrorMessage(ex.Message);
        }


    }


  }

public class AllCountriesData
{
  public string Country { get; set; }
  public ObservableCollection<string> Cities { get; set; }
  public string MyString
  {
     get { return Convert.ToString(Cities); }
     set { }
  }
}

Finally binding it to the comboboxes like so:

<ComboBox x:Name="CmbCountry" 
          ItemsSource="{Binding countryCityData}" 
          DisplayMemberPath="Country"/>

<ComboBox x:Name="CmbCities" 
          ItemsSource="{Binding countryCityData}"
          DisplayMemberPath="Cities"/>

The results of this process is that the "Country" combobox ends up being populated, while the "City" combobox displays a series of items labelled (Collection).

Here's the screenshots of both scenarios. “国家”组合框显示

“城市”组合框显示

What I'd like is for the "Cities" combobox to display the respective cities attached to the "Country" combobox.

What/Where I'm I doing/going wrong and how can I remedy this?

<ComboBox ItemsSource="{Binding SelectedItem.City, ElementName=CmbCountry}"/>

Or more usually you would just have a SelectedCountry on your VM. eg

<ComboBox ItemsSource="{Binding countryCityData}" 
          DisplayMemberPath="Country" 
          SelectedItem="{Binding SelectedCountry}"/>

<ComboBox ItemsSource="{Binding SelectedCountry.City}" 
          SelectedItem="{Binding SelectedCity}"/>

Your AllCountriesData.City would be better named AllCountriesData.Cities since it it a collection of multiple cities.

Bind the second ComboBox to the Cities property of the SelectedItem of the first one:

<ComboBox ItemsSource="{Binding SelectedItem.Cities, ElementName=CmbCountry}"/>

There is no need to set the DisplayMemberPath here since Cities is an IEnumerable<string> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM