# Updating Multiple Collections In ViewModel Based On A Single ListView Selection - WPF

-I have a ListView, and its SelectedItem property is bound to EmployeeModel SelectedEmployee in my VM, and it implements the Set method from MVVM Light. (Basically, OnPropertyChanged, but the MVVM Light version.)

-I have three more ListViews (more, but for simplicity's sake, we'll say three.) They are bound to the following properties in my VM: ObservableCollection<EquipmentAssignmentModel>EquipmentAssignments_StandardIssue, ObservableCollection<EquipmentAssignmentModel>EquipmentAssignments_AdHoc, and <VehicleAssignmentModel>VehicleAssignments.

-EmployeeModel has as these properties: ObservableCollection<EquipmentAssignmentModel>EquipmentAssignments and ObservableCollection<VehicleAssignmentModel>VehicleAssignments.

-When I select a new person in my Employee ListView, SelectedEmployee in my VM is updated. I also want to update the other collections, so that the ListViews display the respective collections. I achieved this by setting the EquipmentAssignment_AdHoc, EquipmentAssignment_StandardIssue, and VehicleAssignment properties in the setter of the SelectedEmployee property. It looks like this:

        private EmployeeModel _selectedEmployee;
public EmployeeModel SelectedEmployee
{
get { return _selectedEmployee; }
set
{
if (Set(ref _selectedEmployee, value))
{
Messenger.Default.Send(new EmployeeToken(value));
if (EquipmentAssignments_StandardIssue != null)
{
EquipmentAssignments_StandardIssue.Clear();
}
{
}
if (SelectedEmployee.EquipmentAssignments != null)
{
var resultFalse = SelectedEmployee.EquipmentAssignments.Where(x => x.IsStandardIssue == false);
var resultTrue = SelectedEmployee.EquipmentAssignments.Where(x => x.IsStandardIssue == true);
if (resultFalse != null )
{
foreach(EquipmentAssignmentRecordModel record in resultFalse)
{
}
}
if (resultTrue !=null)
foreach (EquipmentAssignmentRecordModel record in resultTrue)
{
}
}
}
}
}

public ObservableCollection<VehicleAssignmentRecordModel> VehicleAssignments { get; set; }
public ObservableCollection<EquipmentAssignmentRecordModel> EquipmentAssignments_StandardIssue { get; private set; }
public ObservableCollection<EquipmentAssignmentRecordModel> EquipmentAssignments_AdHoc { get; private set; }


And it works great. Still, since I haven't seen this technique used anywhere else, I'm guessing there is a "right" way to do it that I've not been able to find through Googling.

My first attempt was to use the setters of the three properties to set their own values, so for instance:

private ObservableCollection<EquipmentAssignmentRecordModel>_equipmentAssignments_StandardIssue;
public ObservableCollection<EquipmentAssignmentRecordModel> EquipmentAssignments_StandardIssue
{
get { return _equipmentAssignments_StandardIssue); }
set { _equipmentAssignments_StandardIssue == SelectedEmployee.EquipmentAssignments.Where(x => x.IsStandardIssue == true); }
}


This did not work because even though the SelectedEmployee changed (and indeed it did change in the EquipmentAssignments_StandardIssue setter when I stepped through the code), it didn't notify the ObservableCollections of the change.

So, should I rewrite this code to follow some best practice?

• Please tag the appropriate language. May 13, 2021 at 5:58

Few syntax improvements first:

private EmployeeModel _selectedEmployee;
public EmployeeModel SelectedEmployee
{
get => _selectedEmployee;
set
{
if (Set(ref _selectedEmployee, value))
{
Messenger.Default.Send(new EmployeeToken(value)); // ensure that you don't block the UI Thread for a long time
EquipmentAssignments_StandardIssue?.Clear();
if (SelectedEmployee?.EquipmentAssignments != null)
{
foreach (EquipmentAssignmentRecordModel model in SelectedEmployee.EquipmentAssignments)
{
if (model.IsStandardIssue)
else
}
}
}
}
}


But better to use a couple of ICollectionView as views for SelectedEmployee.EquipmentAssignments. Basically you can create a CollectionView from ObservableCollection, assign a filtering predicate to it and expose it as public property. Then only one ObservableCollection will be in use instead of 3.

Fore example

public ICollectionView EquipmentAssignments_StandardIssue
{
get
{
if (SelectedEmployee?.EquipmentAssignments == null)
return null;
var view = new CollectionViewSource { Source = SelectedEmployee.EquipmentAssignments }.View;
view.Filter = item => item is EquipmentAssignmentRecordModel model && model.IsStandardIssue;
return view;
}
}

{
get
{
if (SelectedEmployee?.EquipmentAssignments == null)
return null;
var view = new CollectionViewSource { Source = SelectedEmployee.EquipmentAssignments }.View;
view.Filter = item => item is EquipmentAssignmentRecordModel model && !model.IsStandardIssue;
return view;
}
}


Then the updating would look like this

public EmployeeModel SelectedEmployee
{
get => _selectedEmployee;
set
{
if (Set(ref _selectedEmployee, value))
{
Messenger.Default.Send(new EmployeeToken(value));
OnPropertyChanged(nameof(EquipmentAssignments_StandardIssue));

The change doesn't affect XAML. Probably there's a better way to do that but I'm not enough strong in collection views. In particular I don't like twice creating CollectionViewSource from the same source in the above code. But the idea might be correct. The main profit of this approach is when you modifying the source collection, both filtered views being updated automatically.
• @JoshuaWhite Mvvm light also has that method but with different name RaisePropertyChanged, you don't need Set there. nameof May 14, 2021 at 17:58
• @JoshuaWhite you don't need Set because there's nothing to set. Just fire PropertyChanged event causing UI to update data from Property getter. May 14, 2021 at 18:06