Событие ObservableCollection PropertyChanged
-
05-07-2019 - |
Вопрос
Хорошо, поэтому я хочу создать подкласс ObservableCollection
, чтобы добавить к нему свойство. К сожалению, событие PropertyChanged
защищено. По сути, я хочу создать подкласс для этого, чтобы иметь SelectedItem
, с которым я могу связываться для списков в моем приложении MVFM WPF.
Вот скелет моего класса:
public class SelectableList<T> : ObservableCollection<T>
{
public T SelectedItem {get;set;}
}
Но я не могу сделать следующее:
SelectableList<int> intList = new SelectableList<int>();
intList.PropertyChanged += new PropertyChangedEventHandler(intList_Changed);
из-за ограничений доступа. Это заставляет меня задать более глубокий вопрос. Почему пользовательский интерфейс может получать уведомления о событиях PropertyChanged
(например, свойство Count), и я не могу сделать это в выделенном коде?
У меня кружится голова, может кто-нибудь просветит меня?
Решение
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
ObservableCollection напрямую реализует INotifyPropertyChanged Это означает, что вы должны привести экземпляр к интерфейсу, прежде чем сможете получить доступ к методам, свойствам и событиям интерфейса. Что касается того, почему это сделано, я не знаю. Привязка разметки extensio n не " ; знать, & Quot; ObservableCollections или любой другой тип. Он проверяет типы, чтобы увидеть, реализуют ли они или расширяют определенные интерфейсы / базовые классы (INPC, INCC, DependencyObject и т. Д.), И поэтому не заботится, реализован ли интерфейс явно.
Другие советы
ObservableCollection (int .NET 3.5), по-видимому, реализует событие PropertyChanged в интересный способ .
protected event PropertyChangedEventHandler PropertyChanged;
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
Это означает, что защищенное событие PropertyChanged , скорее всего, предназначено только для внутренней реализации. Другое событие INotifyPropertyChanged.PropertyChanged - это событие, которое фактически выполняет реализацию интерфейса INotifyPropertyChanged как явный интерфейс . Странно, но я не вижу места в коллекции ObservableCollection, где фактически вызывается INotifyPropertyChanged.PropertyChanged . Это может указывать на то, что это ошибка в .NET 3.5, хотя я не проверял, например, вызывается ли событие измененного свойства для Count при добавлении элемента в коллекцию, но похоже, что он должен работать . р>
В реализации .NET 4.0 кажется, что событие INotifyPropertyChanged.PropertyChanged вместо этого подключается к тому же частному делегату, который используется защищенным событием PropertyChanged , что могло быть ошибкой исправить. Также возможно, что это просто из-за различия в том, как обрабатываются автоматические реализации событий в .NET 4.0 .
Коррекция: я убедился, что событие INotifyPropertyChanged.PropertyChanged вызвано ObservableCollection, поэтому предположения, которые я сделал выше, основаны на результатах использования Reflector для проверки реализации ObservableCollection. должно быть неточным. Я думаю, что отражатель делает странную ошибку, у меня пока нет доказательств этого.
Таким образом, чтобы ваш пример работал, вам нужно написать, чтобы этот пример работал, и выглядел бы как пример ниже, как это продемонстрировал Уилл в своем ответе.
SelectableList<int> intList = new SelectableList<int>();
((INotifyPropertyChanged)intList).PropertyChanged +=
new PropertyChangedEventHandler(intList_Changed);
Интересно, верно? Использование явных интерфейсов в основном используется, чтобы избежать неизбежных коллизий в элементах, необходимых для данного интерфейса, но их можно использовать, чтобы в некотором смысле скрыть существование элемента.
Если вы хотите вызвать события изменения свойств для своих собственных пользовательских свойств, которые вы вводите в своем подклассе, посмотрите на переопределение и / или вызов защищенного метода OnPropertyChanged , который также реализует ObservableCollection. Этот метод является хорошо принятым стандартом и позволяет подклассам вызывать события или обрабатывать события, не имея доступа к базовому делегату события. Обычно предпочитают использовать эту технику, кстати, вместо того, чтобы иметь обработчики событий ловушки подкласса к его собственным событиям базовых классов. Для большего количества примеров посмотрите, как события в различных элементах управления реализованы в WinForms и WPF.
Я попытался добавить новое свойство в
public class ResultCollection<T> : ObservableCollection<T>
{
Boolean _val;
public Boolean Val
{
get
{
return _val;
}
set
{
_val= value;
OnPropertyChanged(new PropertyChangedEventArgs("Val"));
}
}
}
Я действительно не заметил, что PropertyChanged определяется как защищенный . Наконец, свойство Val перемещено в ViewModel.
Пользовательский интерфейс может получать уведомления. Это ограничение JUST для ObservableCollection, которое определяет событие PropertyChanged как защищенное.
FWIW, я думаю, вам лучше оставить ObservableCollection в одиночку и просто добавить другое свойство в вашу виртуальную машину.