Как поднять OnPropertyChanged только для видимых элементов? - PullRequest
2 голосов
/ 22 декабря 2011

У меня очень большая сетка. Я хочу использовать CheckBox «проверить / снять все», который будет проверять / снимать все строки. Но это очень медленно, потому что есть много вызовов события OnPtopertyChanged. Как вызвать событие OnPropertyChanged только для видимых элементов? Виртуализация строк включена.

Ответы [ 4 ]

1 голос
/ 22 декабря 2011

20000 строк много:)

что произойдет, если вы отключите привязку ItemsSource, измените свой список в своей модели представления и установите для itemssource новый проверенный список?

в противном случае, если они хотят 20000, они могут подождать;)

EDIT

если вы не изменили свой источник предметов, вы должны поднять свойство изменено для каждого предмета, в противном случае вы не увидите изменений.

другой способ - установить привязку на ноль или новый список.

  this.MyGridItemsViewModelProperty = new List();//"disconnect" the binding to the grid for the all check/uncheck

затем измените свой реальный список с помощью флажка / снимите флажок и установите его в качестве сетки ItemsSource

   this.MyGridItemsViewModelProperty = myupdatelist;

сетка

   <Grid ItemsSource="{Binding MyGridItemsViewModelProperty}" />

но я не знаю, если второй подход быстрее, вы должны проверить его.

0 голосов
/ 22 декабря 2011

Первый подход: снять поднятие 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 
}
0 голосов
/ 22 декабря 2011

Обновление 1 Я после создания простого репродукции со строками по 100 КБ, которое запускается на моем ПК с низкой спецификацией, не могли бы вы проверить его на своем и подтвердить, достаточно ли он быстр?Имя проекта 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>
0 голосов
/ 22 декабря 2011

Один из способов справиться с этим - иметь свойство boolean IsVisible во ViewModel.Если IsVisible возвращает true только тогда, вы можете вызвать событие PropertyChanged.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...