0

Below I have a ListView with cities, when city is checked then the second list (with persons) must displays persons only from this city.

<ListView ItemsSource="{Binding Cities}">
     <ListView.ItemTemplate >
          <DataTemplate>
               <StackPanel>
                    <Label Content="{Binding Name}" />
                    <CheckBox IsChecked="{Bidning IsChecked}" />
               </StackPanel>
          </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

And the second list view with persons:

<ListView ItemsSource="{Binding Persons}">
     <ListView.ItemTemplate >
          <DataTemplate>
               <StackPanel>
                    <Label Content="{Binding Name}" />
                    <Label Content="{Bidning Surname}" />
               </StackPanel>
          </DataTemplate>
     </ListView.ItemTemplate>
</ListView>

Below you can see view model with the lists which are binded with ListViews.

    public ListCollectionView Cities
    {
        get { return _cities; }
        set
        {
            _cities = value;
            RaisePropertyChanged();
        }
    }

    public ListCollectionView Persons
    {
            get { return _persons; }
            set
            {
                _persons= value;
                RaisePropertyChanged();
            }
     }

The question is how to handle when checkbox which is inside Cities ListView is checked by the user, so I can refresh the Persons list and return Persons only from checked City? I do not know what should I write in View Model, so I do not know how to handle when ListView children property has changed changed.

3
  • You can manage selected city and update a person list, when it changes Commented Jan 23, 2020 at 12:48
  • As a note, the type of the Cities and Persons collections should not be ListCollectionView, but instead List<T> or ObservableCollection<T>, where T is City or Person. Commented Jan 23, 2020 at 12:49
  • If a given person is associated with a specific city then I'd expect a City to have an observablecollection of Person as one of it's properties. You could then bind itemssource of the people listview to selectedCity.People. Remove the checkbox from the City itemtemplate and use selection of City to drive which city' s people are of interest. You would also need to bind selecteditem of cities or bind the people listview to selecteditem.People of the cities listview. Commented Jan 23, 2020 at 13:00

3 Answers 3

0

you have to add public City SelectedCity property to the view model and bind the selected city value in the view

<ListView ItemsSource="{Binding Cities}" SelectedItem="{Binding SelectedCity">

in the SelectedCity setter you can update the Persons collection like

class PersonsByCitiesViewModel
{
public City SelectedCity
{
get{}
set
{
  Persons = LoadPersons(value);
}
}

public ListCollectionView LoadPersons(City selected)
{
  var persons = LoadAll();
  if (selected != null)
    persons = persons.Where(_ => _.CityId = selected.CityId);
  return new ListCollectionView(persons);
}
}
Sign up to request clarification or add additional context in comments.

3 Comments

It will works when I Select one children from the list, but I want to be able to select more than one children (check more than one checkbox) The solution is to rebuild property IsChecked inside City class: public bool IsChecked { get => _isChecked; set { _isChecked = value; OnPropertyChanged(); }
but in City class even I can handle when checkbox is checked I do not have an access to Person Collection, because I am in City class... So I still do not know what to do
You can check new City.Selected property in the PersonsByCitiesViewModel.LoadPersons method (or put list of selected cities to the loader class). However some magic has to be used to filter Persons when user clicks on city checkbox. You can try to implement it 2. Two way binding answer. Or you can add LoadPersons button to be used by the user to initiate loading persons process
0

Handling SelectedItem is good but only if I want to select just one City from the list. What If I want to select more than one?

I have tried to handle property IsChecked inside Cities class, but in Cities class I do not have an access to other elements which are in View Model where Cities List and Person list are.

Comments

0

I recommend handling the Checked and Unchecked event of the CheckBox elements.

View:

<ListView ItemsSource="{Binding Cities}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Label Content="{Binding CityName}" />
                <CheckBox IsChecked="{Binding IsChecked}">
                     <i:Interaction.Triggers>
                         <i:EventTrigger EventName="Checked">
                             <i:InvokeCommandAction Command="{Binding DataContext.SelectedCitiesChangedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
                         </i:EventTrigger>
                         <i:EventTrigger EventName="Unchecked">
                             <i:InvokeCommandAction Command="{Binding DataContext.SelectedCitiesChangedCommand, RelativeSource={RelativeSource AncestorType=ListView}}"/>
                         </i:EventTrigger>
                     </i:Interaction.Triggers>
                </CheckBox>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

<ListView ItemsSource="{Binding ShownPeople}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <Label Content="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

ViewModel:

public List<City> Cities { get; } = new List<City>();

public List<Person> Persons { get; } = new List<Person>();

public ObservableCollection<Person> ShownPeople { get; } = new ObservableCollection<Person>();


public ICommand SelectedCitiesChangedCommand { get; }


public ViewModel()
{
    SelectedCitiesChangedCommand = new DelegateCommand(SelectedCitiesChanged);
}


private void SelectedCitiesChanged()
{
    var checkedCities = Cities.Where(city => city.IsChecked);

    ShownPeople.Clear();
    ShownPeople.AddRange(Persons.Where(person => checkedCities.Any(city => city.CityName == person.City)));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.