MVVM: Должен ли объект VM предоставлять объект M напрямую или только через геттеры, делегирующие геттерам M? - PullRequest
31 голосов
/ 12 июля 2009

лучший способ объяснить это на примере так:

это модель

public class Person 
{
    public int age;
    public string name;
}

это модель вида

public class PersonVM
{    
}

мой вопрос:
должен ли виртуальный компьютер предоставить человеку шаблон данных или инкапсулировать свойства модели с его собственными свойствами?

Ответы [ 4 ]

36 голосов
/ 14 июля 2009

По этому вопросу нет общего согласия. Например, это был один из открытых вопросов о MVVM, сформулированный Уордом Беллом здесь :

Разрешено ли ВМ предлагать V развернутый M-объект (например, необработанный Работник) ? Или M-объект должен свойства (если это даже разрешено есть свойства!) разоблачаться исключительно через поверхность Обертка VM?

Основными преимуществами прямого показа Модели в ВМ являются:

  • Вы можете использовать его как «конвертер стероидов», форматируя значения модели удобным способом для просмотра

  • вы можете добавить другую функциональность, связанную с пользовательским интерфейсом, например сообщения проверки данных , отменить повтор , ..

Минусы:

  • вам придется продублировать много кода, чтобы раскрыть все свойства моделей в модели представления.

  • если вы привяжете элемент управления view к свойству viewmodels, вы отправите события propertyChanged из viewmodel. Но что произойдет, если свойство модели изменяется из другого источника, отличного от установщика viewmodel? Затем он должен уведомить модель представления, чтобы вы закончили с 2 OnPropertyChanged, один в модели и один в модели представления ... довольно сложный!

Так что для меня правильный ответ: это зависит от ваших требований.

21 голосов
/ 12 июля 2009

Модель представления должна объявлять свои собственные свойства и скрывать особенности модели от представления. Это дает вам максимальную гибкость и помогает предотвратить просачивание проблем типа модели в классы модели. Обычно классы модели представления инкапсулируют модель путем делегирования. Например,

class PersonModel {
    public string Name { get; set; }
}

class PersonViewModel {
    private PersonModel Person { get; set;}
    public string Name { get { return this.Person.Name; } }
    public bool IsSelected { get; set; } // example of state exposed by view model

    public PersonViewModel(PersonModel person) {
        this.Person = person;
    }
}

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

6 голосов
/ 05 января 2011

Интересное решение для этого было предложено Робертом Маккартером в томе 25 MSDN.

http://msdn.microsoft.com/en-us/magazine/ff798279.aspx

Он использует динамическую модель представления для предоставления слоя поверх Модели, избегая при этом проксирования всех свойств модели.

Если ваше проблемное пространство не требует высокой производительности (динамика влечет за собой снижение производительности), это отличное решение. Представлению не нужно ничего знать о модели, но модели представления не нужно передавать свойства прокси, которые предоставляются «как есть». В любое время свойства могут быть добавлены в модель представления, чтобы обернуть свойства модели без изменения вида или модели. Прочитайте статью для более подробной информации.

5 голосов
/ 18 апреля 2010

Наличие ViewModel для любой модели может быть хуже, чем это. Что если у вас есть иерархическая структура модели или даже простая коллекция? В этом случае вам придется перебирать все модели и создавать экземпляр ViewModel для каждой модели, а также регистрировать события уведомления-изменения или другие события. ИМХО, это совершенно безумно и необоснованно. Как сказал DaniCE, у вас будет много кода и сильная головная боль.

...