C# 如何提高OnPropertyChanged仅适用于可见元素?

C# 如何提高OnPropertyChanged仅适用于可见元素?,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,我有非常大的网格。我想使用复选框“check/uncheck all”,它将选中/取消选中所有行。但是它非常慢,因为OnPtopertyChanged事件的调用非常多。如何仅针对可见元素引发OnPropertyChanged事件?行的虚拟化已启用。处理此问题的一种方法是在ViewModel中使用布尔IsVisible属性。如果IsVisible仅返回true,则可以引发PropertyChanged事件。20000行很多:) 如果断开ItemsSource绑定并更改viewmodel中的列表并将

我有非常大的网格。我想使用复选框“check/uncheck all”,它将选中/取消选中所有行。但是它非常慢,因为OnPtopertyChanged事件的调用非常多。如何仅针对可见元素引发OnPropertyChanged事件?行的虚拟化已启用。

处理此问题的一种方法是在ViewModel中使用
布尔IsVisible
属性。如果
IsVisible
仅返回
true
,则可以引发
PropertyChanged
事件。

20000行很多:)

如果断开ItemsSource绑定并更改viewmodel中的列表并将ItemsSource设置为新的选中列表,会发生什么情况

oterwise如果他们想要20000排,他们可以等待;)

编辑

如果你不改变你的物品来源,你必须提高每个物品的属性改变,否则你看不到改变

另一种方法是将绑定设置为null或newlist

  this.MyGridItemsViewModelProperty = new List();//"disconnect" the binding to the grid for the all check/uncheck
然后用check/uncheck更改您的真实列表,并将其设置回网格项源

   this.MyGridItemsViewModelProperty = myupdatelist;
网格



但是我不知道第二种方法是否更快,你应该测试它。

更新1我在创建了一个简单的复制程序,有10万行,它在我的低规格PC上飞行,你能在你的电脑上检查它,并确认它是否足够快吗?项目名称为
GroupSelect
,然后将内容复制到主窗口中

代码:

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
使用系统组件模型;
使用System.Collections.ObjectModel;
使用System.Collections.Specialized;
命名空间组选择
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
这个,上膛了+=
(o,e)=>
{
这是DataContext=
新型号(100000);
};
}
}
公共类模型:INotifyPropertyChanged
{
private bool?isAllSelected=null;
公共模型(int itemCount)
{
这是一个项目=
Enumerable.Range(1,itemCount)。选择(t=>
新项目(本)
{
Name=“n_”+t.ToString()
}).ToList();
this.IsAllSelected=false;
}
公共清单项目
{
得到;
私人设置;
}
公共图书馆?全部被选中
{
得到
{
返回此项。isAllSelected;
}
设置
{
如果(this.IsAllSelected!=值)
{
this.IsBatchUpdate=true;//正在更新
this.isAllSelected=值;
if(this.PropertyChanged!=null)
{
这个。财产改变了(这个,
新的属性ChangedEventArgs(“IsAllSelected”);
}
//
if(this.IsAllSelected.HasValue)
{
foreach(本文件中的项目i.Items)
{
i、 IsSelected=value.value;
}
}
this.IsBatchUpdate=false;//正在更新
}
}
}
公共bool-IsBatchUpdate
{
得到;
私人设置;
}
公共事件属性更改事件处理程序属性更改;
}
公共类项目:INotifyPropertyChanged
{
private bool isSelected=假;
公共项目(模型)
{
这个模型=模型;
}
公共模型
{
得到;
私人设置;
}
公共字符串名
{
得到;
设置
}
公选学校
{
得到
{
返回此项。已选择;
}
设置
{
if(this.IsSelected!=值)
{
this.isSelected=值;
if(this.PropertyChanged!=null)
{
这个。财产改变了(这个,
新的房地产变更发展目标(“IsSelected”);
}
如果(!this.Model.IsBatchUpdate)
{
this.Model.IsAllSelected=null;
}
}
}
}
公共事件属性更改事件处理程序属性更改;
}
}
标记:

<Window x:Class="GroupSelect.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:GroupSelect"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="g" AutoGenerateColumns="False" 
                  ItemsSource="{Binding Path='Items'}">
            <DataGrid.Columns>
                <DataGridCheckBoxColumn Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}">
                    <DataGridCheckBoxColumn.HeaderTemplate>
                        <DataTemplate>
                            <CheckBox HorizontalAlignment="Center" 
                                      DataContext="{Binding Path=DataContext, 
                                      RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                      IsChecked="{Binding Path=IsAllSelected, UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </DataGridCheckBoxColumn.HeaderTemplate>
                </DataGridCheckBoxColumn>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

第一种方法:删除OnPropertyChanged的提升并添加dataGrid.Items.Refresh()

第二种方法:静默地更改属性,然后

var rows = grid.FindChildren<DataGridRowsPresenter>().First() as DependencyObject;
int count = VisualTreeHelper.GetChildrenCount(rows);
for (int i = 0; i < count; i++)
{
    DataGridRow row = VisualTreeHelper.GetChild(rows, i) as DataGridRow;
    (row.DataContext as IViewModel).Refresh();//Refresh invokes OnPropertyChanged 
}
var rows=grid.FindChildren().First()作为DependencyObject;
int count=VisualTreeHelper.GetChildrenCount(行);
for(int i=0;i
唯一的问题是如何为虚拟化网格设置这些IsVisible标志:)我的意思是为您的MV设置:)您正在挑战WPF的基础知识。要做到这一点并不容易。你考虑过了吗?
<Window x:Class="GroupSelect.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:GroupSelect"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="g" AutoGenerateColumns="False" 
                  ItemsSource="{Binding Path='Items'}">
            <DataGrid.Columns>
                <DataGridCheckBoxColumn Binding="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}">
                    <DataGridCheckBoxColumn.HeaderTemplate>
                        <DataTemplate>
                            <CheckBox HorizontalAlignment="Center" 
                                      DataContext="{Binding Path=DataContext, 
                                      RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
                                      IsChecked="{Binding Path=IsAllSelected, UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </DataGridCheckBoxColumn.HeaderTemplate>
                </DataGridCheckBoxColumn>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
var rows = grid.FindChildren<DataGridRowsPresenter>().First() as DependencyObject;
int count = VisualTreeHelper.GetChildrenCount(rows);
for (int i = 0; i < count; i++)
{
    DataGridRow row = VisualTreeHelper.GetChild(rows, i) as DataGridRow;
    (row.DataContext as IViewModel).Refresh();//Refresh invokes OnPropertyChanged 
}