I am sharing a the same collection of items among several view models in a DataGrid. When one item on this shared list is selected, I need it to disappear from the list of the others items.
Here are the different view models used:
ParentViewModel.cs
public class ParentViewModel
{
private readonly ObservableCollection<SharedItemViewModel> _sharedItems;
public ParentViewModel()
{
// Shared items
_sharedItems = new ObservableCollection<SharedItemViewModel>
{
new SharedItemViewModel { Visible = true },
new SharedItemViewModel { Visible = true }
};
this.Children = new ObservableCollection<ChildViewModel>
{
// Each child references the same list
new ChildViewModel(_sharedItems),
new ChildViewModel(_sharedItems)
}
}
public ObservableCollection<ChildViewModel> Children { get; }
}
SharedItemViewModel.cs
public class SharedItemViewModel
{
private bool _visible;
public bool Visible
{
get => _visible;
set => this.UpdateProperty(ref _visible, value); // Raises the PropertyChanged event properly
}
}
ChildViewModel.cs
public class ChildViewModel
{
private SharedItemViewModel _selectedItem;
public ChildViewModel(ObservableCollection<SharedItemViewModel> sharedItems)
{
this.Items = sharedItems;
}
public ObservableCollection<SharedItemViewModel> Items { get; }
public SharedItemViewModel SelectedItem
{
get => _selectedItem;
set
{
if(_selectedItem != value)
{
// Set the old item visible again
if (_selectedItem != null)
{
_selectedItem.Visible = true;
}
_selectedItem = value;
// Set the new item not visible
if (value != null)
{
_selectedItem.Visible = false;
}
this.NotifyPropertyChanged();
}
}
}
}
To do so, I am trying to use a different CollectionViewSource
for each row:
MyView.xaml
<DataGrid
ItemsSource="{Binding Children}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Item">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.Resources>
<CollectionViewSource
x:Key="LocalItems"
Source="{Binding Items, Mode=OneWay}"
Filter="CollectionViewSource_Filter"
IsLiveFilteringRequested="True">
<CollectionViewSource.LiveFilteringProperties>
<sys:String>Visible</sys:String>
</CollectionViewSource.LiveFilteringProperties>
</CollectionViewSource>
</Grid.Resources>
<ComboBox
ItemsSource="{Binding Source={StaticResource LocalItems}}"
SelectedItem="{Binding SelectedItem}"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
MyView.xaml.cs
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
e.Accepted = [..]; // Some work here to do to decide whether the item should be visible
}
When I run the application, the shared items are well bound to the comboboxes. When I select one item in one combobox, the Visible
property is well set and the PropertyChanged
event is well raised.
My issue is that I never (neither at loading nor when the Visible
property changed) hit the Filter
handler in my code-behind (tested with a breakpoint).
Do you know what is wrong with this code?