Обновление нескольких выбранных объектов INofityPropertyChange в DataGridView
-
03-07-2019 - |
Вопрос
Я работаю с DataGridView
(Формы Windows) с включенным MultiSelect, который помещен в пользовательский элемент управления.Я хотел бы обновить все выбранные строки вне пользовательского элемента управления, вызвав общедоступный метод, реализующий следующий код:
foreach(DataGridViewRow dr in dataGridView.SelectedRows)
{
MyBusiness business = (MyBusiness)dr.DataBoundItem;
business.Rating = 5;
}
К сожалению, когда выбрано несколько строк, только одна DataGridViewRow
немедленно обновляется, а именно тот, который был выбран последним.Базовые объекты изменяются, и запускается событие NotifyPropertyChange.Более того, когда я меняю выбор после обновления, я вижу, что все строки обновляются именно так, как мне хотелось бы, чтобы они были немедленно.
Во-вторых, очень странно:Когда я установил точку останова в Setter Rating
-property, где запускается NotifyPropertyChange, и подождите несколько секунд, прежде чем продолжить выполнение кода, все работает хорошо (все строки немедленно обновляются).Если я не буду ждать, а очень быстро нажимаю F5 каждый раз при прохождении точки останова, я получу эффект, описанный выше.
Мой бизнес-объект выглядит так (конечно, значительно сокращенно):
public class MyBusiness : INotifyPropertyChanged
{
private int _rating;
public int Rating
{
get { return _rating; }
set
{
if(_rating != value)
{
_rating = value;
NotifyPropertyChanged("Rating");
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
Кто-нибудь уже заметил такое поведение или даже знает решение (или обходной путь)?
Решение
Если ваш DGV привязан к обычному списку, он подписывается только на событие PropertyChanged для выбранной в данный момент строки.Вместо этого попробуйте использовать BindingList или вызвать BindingSource.ResetItem(n) для каждого измененного элемента.
MSDN приводит пример который использует BindingList, а также (бессмысленно) вызывает ResetItem.Поиграйтесь с их примером, и вы увидите, что либо удаление вызова ResetItem, либо замена BindingList обычным List<> будет работать так, как задумано.