Я относительно новичок в MVVM, и я пытаюсь понять, как работает интерфейс INotifyPropertyChanged и как его реализовать в моих моделях. Подход, который я решил принять, - это реализовать его в каждом из моих классов бизнес-объектов.
Проблема с этим подходом заключается в том, что когда я привязываю свой вид к свойству в базовом классе, событие PropertyChanged в этом базовом классе никогда не инициализируется (равно null), и поэтому представление не обновляет данные для этого элемента при изменении моей модели , Я смог воспроизвести проблему с приведенным ниже примером.MVVM INotifyPropertyChanged конфликт с базовым классом PropertyChange
У меня есть класс Person Base:
public class Person : INotifyPropertyChanged
{
#region INotifyProperty
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public String Name
{
get
{
return _name;
}
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
private String _name;
}
И у меня есть класс Employee, унаследованный от моего лица Базового класса:
public class Employee : Person,INotifyPropertyChanged
{
#region INotifyProperty
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public String EmployeeID
{
get
{
return _employeeId;
}
set
{
_employeeId = value;
RaisePropertyChanged("EmployeeID");
}
}
private String _employeeId;
}
Вот мой вид Модели:
public class ViewModel : ViewModelBase<ViewModel>
{
private Employee _employee;
public ViewModel()
{
ChangeModelCommand = new RelayCommand(param=>this.ChangeModel() , param=>this.CanChangeModel);
Employee = new Employee()
{
Name = "BOB",EmployeeID = "1234"
};
}
public ICommand ChangeModelCommand { get; set; }
public Employee Employee
{
get
{
return _employee;
}
set
{
this._employee = value;
NotifyPropertyChanged(m=>m.Employee);
}
}
public void ChangeModel()
{
MessageBox.Show("CHANGING MODEL");
this.Employee.Name = "MIKE";
this.Employee.EmployeeID = "5678";
}
public bool CanChangeModel
{
get{ return true;}
}
}
И, наконец, мой Вид:
<Window.Resources>
<MVVM_NotificationTest:ViewModel x:Key="Model"></MVVM_NotificationTest:ViewModel>
</Window.Resources>
<Grid DataContext="{StaticResource Model}">
<StackPanel>
<Label Content="Employee Name"/>
<TextBox Text="{Binding Path=Employee.Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Label Content="Employee ID"/>
<TextBox Text="{Binding Path=Employee.EmployeeID,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
<Button Content="Change Model" Height="30" Width="100" Margin="5" Command="{Binding Path=ChangeModelCommand}"/>
</StackPanel>
</Grid>
В этом примере я инициализирую свое свойство VM сотрудника в конструкторе виртуальной машины, а затем у меня есть команда изменить EmployeeID (из класса Employee) и Name (из класса Person). Однако единственным элементом пользовательского интерфейса в представлении, который обновляется, является EmployeeID, а не имя (я ожидал, что Боб обновится до Майка).
Во время отладки я обнаружил, что событие PropertyChanged всегда было нулевым в моем базовом классе (Person). Я также заметил, что когда я удаляю весь класс #INotifyProperty из моего класса Employee, все работает отлично, поскольку он использует событие и методы Base Type.
Проблема, с которой я сталкиваюсь, заключается в том, что все мои текущие классы моделей реализуют явно INotifyPropertyChanged. Все они определяют событие PropertyChanged и реализуют метод RaisePropertyChanged, который, очевидно, повлияет на мои привязки в моем приложении MVVM.
Наконец, я хочу уточнить, что я не хочу обматывать свойства модели в моей модели ViewModel и полагаться на механизм VM INPC. Я хотел бы использовать уже реализованную реализацию модели INPC, не имея необходимости условно удалять реализации INPC в зависимости от того, наследую ли я базовый тип или нет.
В целом, я хотел бы знать, что является лучшим способом реализации INPC в моей глубоко иерархической модели, так что наследование не нарушает распространение PropertyEvent, как мы видели в этом примере, и поэтому мои независимые классы могут быть самодостаточными также. Любые идеи или предложения будут очень благодарны :)
Именно то, о чем я думал: p –
Привет @RichardOD, я просто попробовал это, но, похоже, не работал. Он работает только тогда, когда я перемещаю как объявление PropertyChanged, так и метод RaisePropertyChanged в базовый класс ... –
Проблема в том, что у меня есть много классов, генерируемых динамически, поэтому реализация INPC была добавлена массивно для каждого класса. Если это решение, тогда мне нужно будет иметь более сложную логику, чтобы исключить реализацию, когда она унаследована от базового класса :( –