我在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;
}
}