Вызывает ли WPF DataGrid событие при добавлении / удалении строки?

Я хочу пересчитывать вещи каждый раз, когда DataGrid получает больше строк или некоторые удаляются. Я пытался использоватьLoaded событие, но это было сделано только один раз.

я нашелAddingNewItem, но это срабатывает до того, как было добавлено. Мне нужно делать свои вещиafterwards.

Там такжеLayoutUpdated, который работает, но я боюсь, что не стоит использовать его, потому что он срабатывает слишком часто для моих целей.

Ответы на вопрос(7)

DataGrid.LoadingRow(object sender, DataGridRowEventArgs e)?

То же самое для разгрузки.

DataGrid.UnLoadingRow(object sender, DataGridRowEventArgs e)?

 31 мая 2018 г., 03:31
Смотрите мой ответ для правильного способа сделать это
 30 мая 2018 г., 05:21
Разгрузка пожаров, просто отойдя от ряда, а не только для удаления
 02 июл. 2012 г., 14:34
В этом случае свяжите свою сетку данных сObservableCollection.
 02 июл. 2012 г., 14:29
Вы можете добавить новые строки в источник данныхDataGrid без этого события стрельба. Это событие связано с визуальными строками (DataGridRow объекты), а не строки в источнике данных.

я о добавлении или другой операции, лучше всего использовать INotifyCollectionChanged

var source = datagrid.ItemsSource as INotifyCollectionChanged;

Потому что, когда вы развернетеObservableCollection<MyClass>(), ты должен писать строго MyClass (неObservableCollection<ParentOfMyClass>())

и я нашел идеальное событие, чтобы справиться с этим, событие называетсяUnloadingRow

<DataGrid ....
    UnloadingRow="DataGrid_UnloadingRow">
 ...
</DataGrid>

В вашем коде C # вы получите это

private void ProductsDataGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
{
   MyObject obj = (MyObject)e.Row.Item; // get the deleted item to handle it
   // Rest of your code ...
   // For example : deleting the object from DB using entityframework

}
 02 февр. 2017 г., 00:05
Это работает, когда любая строка выгружается визуально, а не логически; таким образом, он будет запускаться каждый раз, когда строка выгружается, и, если виртуализация происходит, это может произойти независимо от того, существовал ли элемент до операции. Идеальное поведение - запускать только тогда, когда элемент добавлен или удален из базовой коллекции.
 31 мая 2018 г., 03:31
Смотрите мой ответ для правильного способа сделать это
 30 мая 2018 г., 05:21
Разгрузка пожаров, просто отойдя от ряда, а не только для удаления

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

Однако, играя вокруг, я обнаружил, что когда удаляется строкаSelectedItem свойство сетки равно нулю, в то время какCurrentItem свойство не является нулевым, и до сих пор я видел эту комбинацию только для удаленной строки (хотя я не могу гарантировать, что я не пропустил экзотическую ситуацию ... однако для базовых ситуаций отхода от строки, которую я имею) пока не видел).

Поэтому, когда можно использовать следующий код для фильтрации только удаленных строк:

private void CategoriesGrid_UnloadingRow(object sender, DataGridRowEventArgs e)
{     
        if (((DataGrid)sender).SelectedItem != null || ((DataGrid)sender).CurrentItem == null)
        {
            return;
        }

        // The rest of your code goes here
}

что "вещи" Если вы хотите пересчитать, вы можете рассмотреть возможность использования вложенного события ScrollViewer.ScrollChanged. Это может быть установлено в XAML следующим образом:

<DataGrid
...
ScrollViewer.ScrollChanged="control_ScrollChanged">

ScrollChangedEventArgs Объект имеет различные свойства, которые могут быть полезны для вычисления макета и положения прокрутки (Extent, Offset, Viewport). Обратите внимание, что они обычно измеряются количеством строк / столбцов при использовании настроек виртуализации по умолчанию.

Решение Вопроса

DataGrid связано с чем-то, я думаю о двух способах сделать это.

Вы можете попробовать получитьDataGrid.ItemsSource сбор и подписка на егоCollectionChanged событие. Это будет работать, только если вы знаете, какой тип коллекции это в первую очередь.

// Be warned that the `Loaded` event runs anytime the window loads into view,
// so you will probably want to include an Unloaded event that detaches the
// collection
private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
    var dg = (DataGrid)sender;
    if (dg == null || dg.ItemsSource == null) return;

    var sourceCollection = dg.ItemsSource as ObservableCollection<ViewModelBase>;
    if (sourceCollection == null) return;

    sourceCollection .CollectionChanged += 
        new NotifyCollectionChangedEventHandler(DataGrid_CollectionChanged);
}

void DataGrid_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // Execute your logic here
}

Другое решение состояло бы в том, чтобы использовать систему событий, такую как Microsoft Prism.EventAggregator или MVVM Light 'sMessenger, Это означает, что вашViewModel будет транслироватьDataCollectionChanged сообщение о событии в любое время изменяется связанная коллекция, и вашView подписаться на получение этих сообщений и выполнять ваш код в любое время, когда они появляются.

С помощьюEventAggregator

// Subscribe
eventAggregator.GetEvent<CollectionChangedMessage>().Subscribe(DoWork);

// Broadcast
eventAggregator.GetEvent<CollectionChangedMessage>().Publish();

С помощьюMessenger

//Subscribe
Messenger.Default.Register<CollectionChangedMessage>(DoWork);

// Broadcast
Messenger.Default.Send<CollectionChangedMessage>()
 28 окт. 2014 г., 23:50
Я пытаюсь реализовать это в своем коде, добавляя обработчик событий, изменяющих коллекцию уведомлений, но моя sourceCollection всегда равна & quot; null & quot ;. У меня нет ViewModelBase в качестве доступного класса для шаблона ObservableCollection. , , Я использую связывание VS 20113 (экспресс) с базой данных SQLServer 2014 express и приложением WPF. Мне не удалось найти недостающее & quot; использование & quot; директива, которая даст мне ViewModelBase. , , Что я делаю неправильно? Спасибо Пол
 29 окт. 2014 г., 14:27
@PaulGibsonViewModelBase это пользовательский класс, который я обычно реализую на всех моих моделях ViewModel. В вашем случае просто приведите его к любому типу предмета в вашем ItemsSource.
 17 сент. 2015 г., 21:38
Я попробовал второй подход, EventAggregator в Prism. В этом случае, когда новая строка добавляется в DataGrid, фокус уже установлен на следующий элемент. Когда я щелкаю по этой строке, событие запускается, поскольку коллекция действительно изменяется в этой точке. Есть ли что-то, что срабатывает немедленно, когда в сетку данных добавляется новая строка, когда CanUserAddRows имеет значение true?
 29 окт. 2014 г., 14:50
Спасибо за объяснение, это то, что я понял после некоторого поиска в Google. Итак, я попробовал класс таблицы данных, а также класс строки (как общий DataRow, так и определенный класс для моего dataRow) и оба получили null для sourceCollection. , , Я разместил вопрос, который имеет блоки кода здесьlink , , , Я уверен, что я делаю что-то простое неправильно, но не могу найти правильную комбинацию.
 17 сент. 2015 г., 22:19
@Vishal Лично я бы не использовал CanUserAddRows для этого. Я бы либо предоставил пользователям & quot; Добавить & quot; кнопка, которая добавляет запись в исходную коллекцию или предоставляет им пустой элемент, и всякий раз, когда этот пустой элемент заполняется, добавьте новый пустой элемент, чтобы заменить «Новый». строка. Лично я предпочитаю первое решение, так как нахождение лишних пустых строк в сетке часто вводит пользователей в заблуждение и затрудняет проверку, поскольку мне всегда приходится проверять, является ли элемент «новым». вещь

public ObservableCollection<Thing> Items{
get { return _items; }
set{ _items = value; RaisePropertyChanged("Items");  // Do additional processing here 
}
}

Таким образом, вы можете наблюдать за добавлением / удалением элементов без привязки к интерфейсу?

 02 июл. 2012 г., 22:06
Хотя это правильный способ обработки событий, измененных в коллекции, для логики приложения, я думаю, что ОП спрашивает о событиях, измененных в коллекции, для представления, основываясь на некоторых комментариях вanother question of his

Ваш ответ на вопрос