Picker MVVM Two Picker has data relative using Binding

YangShengJiaYangShengJia Member ✭✭
edited April 15 in Xamarin.Forms

I have a model like this ( City.cs in Modle folder)

public class City
    {
        public int Key { get; set; }
        public string Name { get; set; }
        public List<string> Regions { get; set; }
        public City()
        {
            Regions = Regions ?? new List<string>();
        }
    }

Data like this (ViewModel.cs in ViewModel folder)

public List<City> GetCities()
        {
            var c = new List<City>()
            {
                new City() { Key = 1, Name = "Keelung", Regions = { "CenterK", "EastK", "NorthK", "WestK", "SouthK" } },
                new City() { Key = 2, Name = "Hsinchu", Regions = { "HEast", "HNorth", "HCenter" } },
                new City() { Key = 3, Name = "Chiayi", Regions = { "CEast", "CWest" } }
            };
            return  c;
        }

In my view.xaml is

Picker  x:Name="CityPicker"
                             Title= "City"
                             ItemsSource="{Binding CitiesList}"
                              ItemDisplayBinding="{Binding Name}"
                              SelectedItem="{Binding SelectedCity}"/
 Picker  x:Name="RegionPicker" 
                           Title="Region"
                             BindingContext="{x:Reference CityPicker}"
                               ItemsSource="{Binding MyRegion}"
                              ItemDisplayBinding="{Binding Items}"

In my viewmodel.cs is

 public City SelectedCity
{
    get { return _selectedCity; }
    set
    {
        if (_selectedCity != value)
        {
            _selectedCity = value;
            var _myregion = GetCities().Where(x => x.Name == _selectedCity.Name).Select(s => s.Regions);
            OnPropertyChanged();
        }
    }
}
List<string> _myregion;
public List<string> MyRegion
{
    get { return _myregion; }
    set
    {
        if (_myregion != value)
        {
            _myregion = value;
            OnPropertyChanged();
        }
    }
}
public ClinicSearchStartViewModel()
{
    try
    {
        ClinicListResponses = new ObservableRangeCollection<ClinicListResponse>();
        Title = "Search";
        CitiesList = GetCities().OrderBy(k => k.Key).ToList();

        GetClinicListResponsesCommand = new Command<ClinicSearchRequest>(async (clinicsearchrequest)
            => await GetClinicListResponsesAsync(clinicsearchrequest));
    }
    catch (Exception ex)
    {
        throw;
    }
}

How can write a code to make RegionPicker ItemDisplayBinding show CityPicker SelectedItem related Region
for example
CityPicker Select Keelung then click RegionPicker will show { "CenterK", "EastK", "NorthK", "WestK", "SouthK" }

Thanks for Reading````

Best Answer

Answers

  • DirkWilhelmDirkWilhelm USMember ✭✭✭✭

    Hello YangShengJia,

    try this:

     public City SelectedCity
    {
        get { return _selectedCity; }
        set
        {
            if (_selectedCity != value)
            {
                _selectedCity = value;
                MyRegion = GetCities().Where(x => x.Name == _selectedCity.Name).Select(s => s.Regions);
                OnPropertyChanged();
            }
        }
    }
    
  • YangShengJiaYangShengJia Member ✭✭

    Hi DirkWilhelm

    It's will show error

    "Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.List<string>>" to System.Collections.Generic.List<string>
    

    I try to cast using

    MyRegion = (List<string>)GetCities().Where(x => x.Name == _selectedCity.Name).Select(s => s.Regions);
    

    No error, but Debug project Click CityPicker and select one of items show exception
    Exception has been thrown by the target of an invocation.

  • YangShengJiaYangShengJia Member ✭✭

    I rewrite code on ViewModel.cs

    private City _selectedCity { get; set; }
    public City SelectedCity
    {
        get { return _selectedCity; }
        set
        {
            if (value != _selectedCity)
            {
                _selectedCity = value;
                _myregion = GetCities().FirstOrDefault(x => x.Name == _selectedCity.Name).Regions;
                OnPropertyChanged();
            }
        }
    }
    List<string> _myregion = new List<string>();
    public List<string> MyRegion
    {
        get { return _myregion; }
        set
        {
            //_myregion = _myregion ?? new List<string>();
            if (_myregion != value)
            {
                _myregion = value;
                OnPropertyChanged();
            }
        }
    }
    

    It's fixed an error of "Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Collections.Generic.List>" to System.Collections.Generic.List

    In my view

    Picker x:Name="CityPicker"
        Title= "City"
        ItemsSource="{Binding CitiesList}"
        ItemDisplayBinding="{Binding Name}"
        SelectedItem="{Binding SelectedCity}"/>
    Picker x:Name="RegionPicker" 
        Title="Region"
        ItemsSource="{Binding MyRegion}"
        ItemDisplayBinding="{Binding value}"
        />
    

    RegionPick still no show anything

  • YangShengJiaYangShengJia Member ✭✭
    edited April 17

    Well, jezh thanks a lot about your code. Real gave a new thought about how to achieve this goal. but in my code, the citys has 21 items, some items the regions has 38 above. I don't want to give it all has new instance.
    so I write the code when I click the CityPicker and choice city will execute some code

    public City SelectedCity
    {
        get { return _selectedCity; }
        set
        {
            if (value != _selectedCity)
            {
                _selectedCity = value;
                var a = GetCities().FirstOrDefault(x => x.Name == _selectedCity.Name).Regions;
                myregion.Clear();
                foreach (var item in a) //I try use this foreach to create a Bindingable Object
                {
                    myregion.Add(new CityRegion() {
                        RegionName = item
                    });
                }
                OnPropertyChanged();
            }
        }
    }
    List<CityRegion> myregion = new List<CityRegion>();
    public List<CityRegion> MyRegion//this my BindingTarget
    {
        get { return myregion; }
        set
        {
            myregion = value;
            OnPropertyChanged();
        }
    }
    

    In my Model folder(City.cs) I increase new class

        public class CityRegion
        {
           public string RegionName { get; set; }
        }
    

    it's kind of like part of your Region.cs
    everything works ok when I run the project I can see MyRegion will change to the right number of items(RegionName) when I click different city in CityPicker.
    In my view

    Picker x:Name="RegionPicker" 
        ItemsSource="{Binding MyRegion}"
        ItemDisplayBinding="{Binding RegionName}" />
    

    when i click RegionPicker still show nothing, why? It's about ObservableCollection declare, or some theory about mvvm or c# i miss and need to study?

Sign In or Register to comment.