0

I have a page PeopleView which consists of a GridView which displays a list of People. I wish to provide a way of adding a removing from the list of People through a popup user control. The UserControl also allows for searching of all users to add more.

When the UserControl first opens it should display all the People, which it does and any People which are currently visible in the GridView should be already selected in the popup ListView. When a user selects addition People in the UserControl the People collection should be added to and the main GridView reflects this. This all works as intended.

The issue comes when I try to filter the list of People on the popup. This causes the FilteredPeople collection to be reset and as such removes all the selections from the ListView and therefore from the ObservableCollection which clears the GridView on the main page.

I want to search through the People whilst retaining the selection and add and remove from this list whilst searching.

This is the GridView on the main page:

<GridView x:Name="PeopleGridView"
                    Grid.Row="1"
                    Padding="116, 0, 0, 0"
                    ItemsSource="{Binding People}"
                    ItemTemplate="{StaticResource PeopleSelectItemTemplate}"
                    SelectionMode="Multiple" />

On this page is a popup usercontrol which allows for the adding and removing of People from this GridView. It also allows searching of people:

The xaml looks like this:

<TextBlock Style="{StaticResource PopupHeaderTextStyle}"
           Text="Enter person name:"
           TextWrapping="Wrap"/>

<TextBox Grid.Column="1"
         x:Name="SearchFieldTextBox"
         TextChanged="SearchField_Changed"
         Margin="20,0,20,0"
         Height="30" />

<ListView Grid.Row="1"
          Grid.ColumnSpan="2"
          SelectedIndex="1"
          SelectionMode="Multiple"
          ItemsSource="{Binding FilteredPeople}"
          extensions:ListViewExtensions.BindableSelection="{Binding People}"
          ItemTemplate="{StaticResource PeopleSearchItemTemplate}"
          HeaderTemplate="{StaticResource PeopleSearchHeaderTemplate}"/>

People and FilteredPeople are properties on my view model:

private ObservableCollection<PeopleViewModel> _people;
public ObservableCollection<PeopleViewModel> People
{
    get { return people; }
    set
    {
        if (Equals(people, value)) return;

        people = value;
        RaisePropertyChanged(() => People);
    }
}

private IEnumerable<PeopleViewModel> _filteredPeople;
public IEnumerable<PeopleViewModel> FilteredPeople
{
    get { return _filteredPeople; }
    set
    {
        if (_filteredPeople == value) return;

        _filteredPeople = value;
        RaisePropertyChanged(() => FilteredPeople);
    }
}

They are populated on load as such:

FilteredPeople = _allPeople = _peopleService.GetAll();
People = _allPeople.Where(p => p.Selected);

When the search text is entered the FilterPeople method is called on the viewmodel, which looks like this:

private void FilterPeople(string searchField)
{
    FilteredPeople = _allPeople.Where(p => p.Name.Equals(searchField));
    People = FilteredPeople.Where(p => p.Selected);
}

I am using the BindableSelection extension provided by the WinRT XAML Toolkit. When an item in the ListView is selected I update the underlying model object:

void People_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        var person = e.NewItems[0] as PeopleViewModel;
        person.Selected = true;
        _personService.Save(person);
    }
    else if (e.Action == NotifyCollectionChangedAction.Remove)
    {
        var person = e.OldItems[0] as PeopleViewModel;
        person.Selected = false;
        _personService.Save(person);
    }
}

The issue is that the FilteredPeople collection is reset but I can't figure out of way of doing this. I can't find any examples online of how this could be done.

I'm using MVVM Cross is that is any use in this scenario

What am I doing wrong?

Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
JFoulkes
  • 2,429
  • 1
  • 21
  • 24
  • Hmm, this is easy when not multiple select (simply bind a property to SelectedItem). You might want to create a property on the user control that is bound to a SelectedPeople property on the VM that acts as an intermediary between the two... –  Oct 09 '13 at 20:01
  • I don't think that would solve the issue with the selection being cleared when I reset the FilteredPeople collection – JFoulkes Oct 10 '13 at 10:05
  • The `BindableSelection` extension supports some most basic scenarios, but I myself switch to custom code when something doesn't work out. It might be something you could work around or an update you could make to the Toolkit, but really to unblock yourself quickly you should just handle the `SelectionChanged`/`CollectionChanged` events to synchronize the selection in the view and the view model. – Filip Skakun Oct 14 '13 at 16:58

0 Answers0