2013-02-14 2 views
7

Я столкнулся с некоторыми вопросами дизайна в моем приложении MVPM (приложение Prism на основе wpf), был бы рад получить ваш совет. Моя модель очень проста:Добавление INotifyPropertyChanged к модели?

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 
     } 
    } 
} 

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

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

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

Спасибо!

ответ

4

Вариант1.
Отдельные объекты, которые передаются между клиентом и сервером (DTO), из объектов, которые являются моделями на стороне клиента. Внесите INPC в модели. Используйте сопоставление между этими объектами.

Вариант2.
Привилегировать просмотр только для просмотра свойств модели. Сделать свойства модели просмотра, которые обертывают соответствующие свойства модели.

Вариант 3.
Это сочетание первых двух вариантов. Не суммируйте модель в модели. Используйте сопоставление между моделью и моделью просмотра. Сделать свойства модели просмотра, соответствующие свойствам модели.

0

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

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

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

.... 
1

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


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.

+2

Я понимаю, что вы говорите, но это потребует много кодирования (почти) нет оснований. Должен ли я дублировать каждое свойство моей модели в моей модели? – Asaf

+0

@Asaf Вы правы. Я не знаю вашего проекта. Если это всего лишь небольшая, это может быть огромная накладная. Но в крупных проектах, когда у вас есть дополнительные требования, такие как тестируемость, развязка a.s.o. это был бы один из способов их достижения. – DHN

1

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

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

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

Сценарий, например:

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.

0

Если вам не нравится загромождать модель с INotifyPropertyChanged код, который вы могли бы попробовать использовать пакет NuGet под названием PropertyChanged.Fody

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

using PropertyChanged; 

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

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

Смежные вопросы