我有一个
UserControl
,其中包含以下 Xaml,代表一个简单的 DataGrid
,带有用于测试的按钮:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="TestGrid" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding Path=Id}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Content="Init View" Click="InitViewButton_Click"/>
<Button Content="Add" Click="AddButton_Click"/>
<Button Content="Change Ids" Click="ChangeIdButton_Click"/>
<Button Content="Filter X" Click="FilterButton_Click"/>
</StackPanel>
</Grid>
以及(在代码隐藏中)以下代码:
public ListCollectionView TestView {get; set;}
public ObservableCollection<TestItem> TestItems {get; set;}
private void init()
{
var result = new ObservableCollection<TestItem>()
{
new TestItem() { Id = 1, Name = "First A" },
new TestItem() { Id = 2, Name = "Second A" },
new TestItem() { Id = 3, Name = "Third A" },
};
TestItems = result;
var view = new ListCollectionView(TestItems);
view.SortDescriptions.Add(new SortDescription(nameof(TestItem.Id), ListSortDirection.Descending));
view.IsLiveSorting = true;
view.Filter = o => (o as TestItem)?.Name.Contains("A") ?? false;
TestView = view;
}
private void InitViewButton_Click(object sender, RoutedEventArgs e)
{
init();
TestGrid.ItemsSource = TestView;
TestGrid.Items.Refresh();
}
private void AddButton_Click(object sender, RoutedEventArgs e)
{
var item = new TestItem() { Id = 99, Name = "New AX" };
TestItems.Add(item);
}
private void ChangeIdButton_Click(object sender, RoutedEventArgs e)
{
foreach (var testItem in TestItems)
{
testItem.Id = Random.Shared.Next(1000);
}
}
private void FilterButton_Click(object sender, RoutedEventArgs e)
{
TestView.Filter = o => (o as TestItem)?.Name.Contains("X") ?? false;
}
单击“Init View”后,
DataGrid
按预期填充,其他按钮按预期工作,例如更改 Id 时,会对行进行重新排列。
如果我再次单击“Init View”,则一切正常,除了重新排序,即更改 Id 不会重新排序行 - 不过,显示的项目已正确更新。
怎么会这样?
旁注:尽管没有设置
IsLiveFiltering
,过滤仍按预期工作,例如如果我从名称中删除“A”,则该项目将从 DataGrid
中删除。
在将 DataGrid ItemsSource 设置为新的 ListCollectionView 后(第一次之后),SortDescriptions 似乎以某种方式被清除。
如果您在 TestGrid.ItemsSource = TestView 之后添加 SortDescription,则它可以工作。
private void init()
{
var result = new ObservableCollection<TestItem>()
{
new TestItem() { Id = 1, Name = "First A" },
new TestItem() { Id = 2, Name = "Second A" },
new TestItem() { Id = 3, Name = "Third A" },
};
TestItems = result;
var view = new ListCollectionView(TestItems);
view.IsLiveSorting = true;
view.Filter = o => (o as TestItem)?.Name.Contains("A") ?? false;
TestView = view;
}
private void InitViewButton_Click(object sender, RoutedEventArgs e)
{
init();
TestGrid.ItemsSource = TestView;
TestView.SortDescriptions.Add(new SortDescription(nameof(TestItem.Id), ListSortDirection.Descending));
//TestGrid.Items.Refresh();
}