Добавление INotifyPropertyChanged в модель?

я сталкиваюсь с некоторыми вопросами дизайна в моем приложении WPF MVVM (Prism), был бы рад получить ваш совет. Моя модель очень проста:

public class Customer
{
   public string FirstName {get;set;}
   public string LastName {get;set;}
}

Как вы можете видеть, у меня нет поддержки INotifyPropertyChnaged для моего класса модели. У меня также есть ViewModel для экрана CustomerDetails, который поддерживает INotifyPropertyChanged.

public class CustomerDetailsViewModel:INotifyPropertyChanged /*Or NotificationObject*/
{
   /*INotifyPropertyChanged event */
   private Customer item;
   public Customer Item
   {
      get{return item;}
      set
      {
         item=value; 
         //Raise PropertyChanged
         //Set IsDirty to true
      }
   }
}

на мой взгляд, я использую привязку к элементу.FirstName и моя ViewModel обновляются. Моя проблема - так как только Свойство FirstName обновляется через представление, и сама модель не поддерживает INotifyPropertyChanged, поэтому не вызывается задатчик элементов, а IsDirty остается равным false (и поэтому не обновляет уведомление IsDirty в пользовательском интерфейсе).

Я знаю, что могу поддерживать INotifyPropertyChanged в модели, а затем зарегистрироваться в элементе.PropertyChanged событие в модели представления и фактически установить IsDirty в true, но - Поскольку я также использую CodeFirst и мою модель класс, разделяемый между моей серверной и клиентской сторонами (не используя ссылку на службу Add), я не хочу добавлять материал INotifyPreoprtyChanged на мою серверную сторону.

Я создаю новый проект, который будет использовать шаблоны T4 для копирования по одному всех моих сущностей (как клиент) и добавления поддержки INotifyPropertyChanged к каждой модели. Это кажется разумным или нет? есть другие предложения?

спасибо!

5 ответов


Option1.
Отдельные сущности, которые передаются между клиентом и сервером (DTO), от сущностей, которые являются моделями на стороне клиента. Реализовать INPC в модели. Сопоставление между этими сущностями.

Option2.
Bind view для просмотра только свойств модели. Сделать вид, что обертывание соответствующих свойств модели.

3.
Представляет собой смесь первых двух вариантов. Не агрегируйте модель в view model. Сопоставление между модели и посмотреть модель. Создайте свойства модели представления, соответствующие свойствам модели.

Ну это просто не самый лучший. Гораздо лучше было бы использовать VM, как это


public class CustomerDetailsViewModel : INotifyPropertyChanged
{
  public CustomerDetailsViewModel(Customer customer)
  {
    _item = customer;
  }
  private Customer _item;

  public string FirstName
  { 
    get { return _item != null ? _item.FirstName : null; }
    set 
    {
      if (_item == null)
        _item = new Customer(); // just an example, probably it's not the desired behavior
      _item.FirstName = value;
      RaisePropertyChanged(...);
    }
  }
  ...
}

Это будет придерживаться духа MVVM.


если вы хотите, чтобы ваш UI, чтобы заметить, когда ваша модель объекта ваша модель класс должны реализовать INotifyPropertyChanged и аналогичные интерфейсы MVVM (IDataErrorInfo, etc...) для того, чтобы Notify для пользовательского интерфейса, что property changed.

это потому, что вы не всегда обновляете свою модель из viewmodel, где вы должны реализовать INotifyProperyChanged и уведомления об изменениях.

перенос соответствующих свойств модели в viewmodel, используемый при не удается реализовать INotifyPropertyChanged в классе model, что делает viewmodel очень быстрым и создает ненужное дублирование кода.

сценарий к примеру:

public class Customer
{
   public string FirstName {get;set;}
   public string LastName {get;set;}

   // Changes the first name.
   public void ChangeFirstName(string newName)
   {
      FirstName = newName;
      //The UI will never know that the property changed, and it won't update.
   }
}

устранение:

реализовать INotifyPropertyChanged в классе модели создайте backing fields на properties, и для каждого свойства setter, после set операции, поднять OnPropertyChanged вызывается метод с property имя.


Я думаю, что вы на правильном пути. На стороне сервера, вам не нужно INotifyPropertyChanged, поэтому не добавляйте его в классы домена на стороне сервера.

вы можете просто добавить некоторые символы сборки, такие как" WPF", в свои клиентские проекты; и в коде первые определения реализуют INotifyPropertyChanged только если есть символ сборки "WPF". Затем просто добавьте классы домена на стороне сервера в качестве ссылок на приложение презентации. Что-то вроде:

#if WPF
public class MyEntity : INotifyPropertyChanged
#else
public class MyEntity

....

Если вам не нравится загромождать вашу модель кодом INotifyPropertyChanged, вы можете попробовать использовать пакет NUGet под названием PropertyChanged.Фоди!--2-->

вы можете использовать его как это:

using PropertyChanged;

[ImplementPropertyChanged]
public class Customer
{
   public string FirstName {get;set;}
   public string LastName {get;set;}
}

любое публичное свойство в этом классе теперь будет поддерживать INotifyPropertyChanged