Вопрос

Хорошо, поэтому я хочу создать подкласс 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 в одиночку и просто добавить другое свойство в вашу виртуальную машину.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top