Жирные модели, тощие ViewModels и немые взгляды, лучший подход MVVM?

Благодаря щедрой помощи по этому вопросу я собрал следующую структуру MVVM, которая отображает изменения модели в реальном времени в XAML (текущая дата / время), очень приятно.

Приятным преимуществом этой настройки является то, что когда вы смотрите на свой взгляд в режиме разработки Visual Studio или Blend, вы видите время , на которое указывает время , что означает, что во время разработки у вас есть доступ к текущим данным из вашей модели.

В процессе заставить это работать, я был удивлен, увидев большую часть массового перемещения из моей модели ViewModel в мою модель , включая реализацию INotifyPropertyChange. Другое изменение заключается в том, что я больше не привязываюсь к свойствам в ViewModel, а к методам .

Так что в настоящее время это мой любимый вкус MVVM:

  1. Вид немой:

    • один ObjectDataProvider для каждого объекта, который вам нужен из вашей модели
    • каждый ObjectDataProvider сопоставляет методу ViewModel (не свойство)
    • no x: свойства имени в элементах XAML
  2. ViewModel тощий:

    • единственное, что есть в вашей модели ViewModel – это методы, с которыми связано ваше представление.
  3. Модель – это жир:

    • модель реализует INotifyPropertyChanged по каждому свойству.
    • для каждого метода на вашем ViewModel (например, GetCurrentCustomer) в вашей модели есть соответствующий одноэлементный метод (например, GetCurrentCustomer).
    • модель заботится о любых функциях streamовой обработки в реальном времени, как в этом примере

Вопросов:

  1. Те из вас, кто внедрял MVVM в реальных сценариях, – это та базовая структура, на которую вы также опирались, а если нет, то как вы меняетесь?
  2. Как бы вы это расширили, чтобы включить маршрутизированные команды и маршрутизированные события?

Следующий код будет работать, если вы просто скопируете XAML и код в новый проект WPF.

XAML:

               

Код:

 using System.Windows; using System.ComponentModel; using System; using System.Threading; namespace TestBinding99382 { public partial class Window1 : Window { public Window1() { InitializeComponent(); } } //view model public class ShowCustomerViewModel { public Customer GetCurrentCustomer() { return Customer.GetCurrentCustomer(); } } //model public class Customer : INotifyPropertyChanged { private string _firstName; private string _lastName; private DateTime _timeOfMostRecentActivity; private static Customer _currentCustomer; private Timer _timer; public string FirstName { get { return _firstName; } set { _firstName = value; this.RaisePropertyChanged("FirstName"); } } public string LastName { get { return _lastName; } set { _lastName = value; this.RaisePropertyChanged("LastName"); } } public DateTime TimeOfMostRecentActivity { get { return _timeOfMostRecentActivity; } set { _timeOfMostRecentActivity = value; this.RaisePropertyChanged("TimeOfMostRecentActivity"); } } public Customer() { _timer = new Timer(UpdateDateTime, null, 0, 1000); } private void UpdateDateTime(object state) { TimeOfMostRecentActivity = DateTime.Now; } public static Customer GetCurrentCustomer() { if (_currentCustomer == null) { _currentCustomer = new Customer { FirstName = "Jim" , LastName = "Smith" , TimeOfMostRecentActivity = DateTime.Now }; } return _currentCustomer; } //INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } } } 

Вот мое мнение, для чего это стоит:

Я не согласен с предложенным вами подходом (за исключением немого представления). В реальной жизни вам часто придется использовать существующую модель: это может быть устаревший код, в котором у вас нет времени (или будет) для изменения или даже библиотеки, для которой у вас нет кода. На мой взгляд, модель должна полностью не знать, как она будет отображаться, и ее следует легко использовать в приложении, отличном от WPF. Таким образом, он не должен реализовывать какой-либо конкретный интерфейс, такой как INotifyCollectionChanged из INotifyCollectionChanged чтобы он мог использоваться в MVVM. Я думаю, что вся логика, связанная с пользовательским интерфейсом, должна находиться в ViewModel.

Что касается RoutedEvents и RoutedCommands , они не подходят для использования с шаблоном MVVM. Обычно я стараюсь использовать как можно меньше RoutedEvents и вообще никаких RoutedCommands . Вместо этого мои ViewModels предоставляют свойства RelayCommand которые я привязываю к пользовательскому интерфейсу в XAML (подробности см. В этой статье Джоша Смита для RelayCommand ). Когда мне действительно нужно обрабатывать события для какого-либо элемента управления, я использую прикрепленные поведения для сопоставления событий с командами ViewModel (посмотрите на реализацию Marlon Grech )

Итак, вкратце:

  • Тупой взгляд
  • Большой и умный ViewModel
  • Любая модель, которую вы хотите или должны использовать

Конечно, это только мой подход, и это может быть не самое лучшее, но я чувствую себя вполне комфортно с ним;)

Я согласен с Томасом. Мой совет для любого из WPF-архитектуры:

  • Обычные объекты POCO без INotifyPropertyChange, отслеживание состояния, BL и т. Д.
  • Простые и малые ViewModels, которые уведомляют Views точно в срок
  • Простой многоразовый пользовательский интерфейс с интеллектуальной навигационной системой, которая позволяет избежать сложных иерархий данных и сложных базовых ViewModels
  • MVVM с View Первый подход для упрощения зависимостей
  • Асинхронные операции с задачами или Rx
  • Простая тема
  • Нет сложного надежного пользовательского интерфейса, простота использования, просто воспользуйтесь компоновкой пользовательского интерфейса WPF и возможностями связывания
  • Не стесняйтесь использовать код для динамического создания контента (формы, списки и т. Д.) И сэкономить значительное время на декларативной настройке глаз (применимо к большинству случаев) – и для меня обязательно в 2015 году. Используйте методы расширения для создания Fluent API для этого.
  • Кнопки раскраски в Android с материальным дизайном и AppCompat
  • Фабричный, абстрактный заводский и заводской метод
  • TextInputLayout не показывает подсказку EditText перед тем, как пользователь сосредоточится на ней
  • Составные первичные ключи в сравнении с уникальным полем идентификатора объекта
  • Образец торта с отменным абстрактным типом не работает с верхними границами
  • Как создать RESTful поиск / фильтрацию?
  • Существует ли типичный шаблон реализации государственного аппарата?
  • Android разнородный gridview как pinterest?
  • На панели инструментов нет тени по умолчанию?
  • Когда добавляется новая строка в базе данных, необходимо вызвать внешнюю программу командной строки
  • MySQL - дизайн супертипа / подтипа
  • Давайте будем гением компьютера.