我有很大的网格。我想使用CheckBox“check / uncheck all”来检查/取消选中所有行。但它很慢,因为有很多OnPtopertyChanged事件的调用。如何仅为可见元素引发OnPropertyChanged事件?启用了行的虚拟化。
答案 0 :(得分:1)
20000行很多:)
如果断开ItemsSource绑定,改变viewmodel中的列表并将itemssource设置为新的检查列表,会发生什么?
如果他们想要20000个,他们可以等待它;)
修改
如果您不更改您的itemssource,您必须为每个项目提高propertychanged,否则您不会看到更改。
另一种方法是将绑定设置为null或new List
this.MyGridItemsViewModelProperty = new List();//"disconnect" the binding to the grid for the all check/uncheck
然后使用check / uncheck更改您的真实列表,并将其设置为网格ItemsSource
this.MyGridItemsViewModelProperty = myupdatelist;
格
<Grid ItemsSource="{Binding MyGridItemsViewModelProperty}" />
但我不知道第二种方法是否更快,你应该测试它。
答案 1 :(得分:0)
处理此问题的一种方法是在ViewModel中拥有boolean IsVisible
属性。如果IsVisible
仅返回true
,则您可以举起PropertyChanged
事件。
答案 2 :(得分:0)
更新1我在创建了一个100K行的简单repro之后,它在我的低规格PC上飞行,你可以在你的机器上检查它,并且如果它足够快就可以进行压缩吗?项目名称为GroupSelect
,然后将内容复制/过去到主窗口中。
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace GroupSelect
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded +=
(o, e) =>
{
this.DataContext =
new Model(100000);
};
}
}
public class Model : INotifyPropertyChanged
{
private bool? isAllSelected = null;
public Model(int itemCount)
{
this.Items =
Enumerable.Range(1, itemCount).Select(t =>
new Item(this)
{
Name = "n_" + t.ToString()
}).ToList();
this.IsAllSelected = false;
}
public List<Item> Items
{
get;
private set;
}
public bool? IsAllSelected
{
get
{
return this.isAllSelected;
}
set
{
if (this.IsAllSelected != value)
{
this.IsBatchUpdate = true; // updating
this.isAllSelected = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this,
new PropertyChangedEventArgs("IsAllSelected"));
}
//
if (this.IsAllSelected.HasValue)
{
foreach (Item i in this.Items)
{
i.IsSelected = value.Value;
}
}
this.IsBatchUpdate = false; // updating
}
}
}
public bool IsBatchUpdate
{
get;
private set;
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class Item: INotifyPropertyChanged
{
private bool isSelected = false;
public Item(Model model)
{
this.Model = model;
}
public Model Model
{
get;
private set;
}
public string Name
{
get;
set;
}
public bool IsSelected
{
get
{
return this.isSelected;
}
set
{
if (this.IsSelected != value)
{
this.isSelected = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this,
new PropertyChangedEventArgs("IsSelected"));
}
if (!this.Model.IsBatchUpdate)
{
this.Model.IsAllSelected = null;
}
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
标记:
<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>
答案 3 :(得分:0)
第一种方法:删除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
}