CollectionViewSource.Filter不是由Datagrid中同一集合的多个CVS引发的



我在DataGrid中的多个视图模型之间共享相同的项集合。当这个共享列表上的一个项目被选中时,我需要它从其他项目的列表中消失。

以下是使用的不同视图模型:

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();
}
}
}
}

为此,我尝试对每一行使用不同的CollectionViewSource

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
}

当我运行应用程序时,共享项被很好地绑定到组合框。当我在一个组合框中选择一个项目时,Visible属性设置良好,PropertyChanged事件引发良好。

我的问题是,我从来没有(无论是在加载时,还是在Visible属性更改时(在代码后面(使用断点进行测试(碰到过Filter处理程序。

你知道这个代码出了什么问题吗

我不确定为什么没有引发事件,但您可以直接筛选Items源集合,也可以在加载CellTemplate中的Grid时尝试设置视图的Filter属性:

private void Grid_Loaded(object sender, RoutedEventArgs e)
{
Grid grid = (Grid)sender;
CollectionViewSource cvs = grid.Resources["LocalItems"] as CollectionViewSource;
if (cvs != null)
cvs.View.Filter = (s) => true; //your filtering logic here...
}

XAML:

<Grid Loaded="Grid_Loaded">
<Grid.Resources>
<CollectionViewSource x:Key="LocalItems">
...

我找到了一个解决方法,但我不会将其标记为答案,因为它"断裂";通过在我的ViewModel中添加对WindowsBase的依赖项,稍微改进一下MVVM模式。

解决方案包括在ChildViewModel:中构建CollectionViewSource

public class ChildViewModel
{
private SharedItemViewModel _selectedItem;
public ChildViewModel(ObservableCollection<SharedItemViewModel> sharedItems)
{
var cvs = new CollectionViewSource();
cvs.Source = sharedItems;
cvs.IsLiveFilteringRequested = true;
cvs.LiveFilteringProperties.Add(nameof(SharedItemViewModel.Visible));
cvs.View.Filter = this.Filter;
this.Items = cvs.View;
}

public ICollectionView Items { get; }

public SharedItemViewModel SelectedItem {..}

private bool Filter(object obj)
{
var vm = obj as SharedItemViewModel;

return vm.Visible;
}
}

最新更新