如何仅对可见元素引发OnPropertyChanged

本文关键字:OnPropertyChanged 元素 何仅 | 更新日期: 2023-09-27 18:18:30

我有一个非常大的网格。我想使用复选框"选中/取消选中所有",这将选中/取消选中所有行。但是它非常慢,因为有很多调用OnPtopertyChanged事件。我如何提高OnPropertyChanged事件仅为可见的元素?

如何仅对可见元素引发OnPropertyChanged

20000行太多了:)

如果断开ItemsSource绑定,改变视图模型中的列表并将ItemsSource设置为新的选中列表,会发生什么?

否则,如果他们想要20000行,他们可以等待;)

编辑

如果你不改变你的itemssource,你必须为每个item触发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}" />

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

处理这个问题的一种方法是在ViewModel中有一个boolean IsVisible属性。如果IsVisible只返回true,则可以引发PropertyChanged事件。

更新1我创建了一个简单的复制与100K行,它在我的低规格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>

第一种方法:删除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 
}
相关文章:
  • 没有找到相关文章