M-V-VM, модель не просачивается в View? - PullRequest
10 голосов
/ 15 апреля 2010

Суть M-V-VM, как мы все знаем, связана с целым рядом проблем. В таких шаблонах, как MVVM, MVC или MVP, основная цель состоит в том, чтобы отделить представление от данных, тем самым создав более гибкие компоненты. Сначала я продемонстрирую очень распространенный сценарий, встречающийся во многих приложениях WPF, а затем выскажу свое мнение:

Скажем, у нас есть приложение StockQuote, которое выводит кучу цитат и отображает их на экране. Как правило, у вас будет это:

StockQuote.cs: (модель)

    public class StockQuote
    {
       public string Symbol { get; set; }
       public double Price { get; set; }
    }

StockQuoteViewModel.cs: (ViewModel)

   public class StockQuoteViewModel
   {
      private ObservableCollection<StockQuote> _quotes = new ObservableCollection<StockQuote>();

      public ObservableCollection<StockQuote> Quotes 
      {
         get
         {
            return _quotes;
         }
      }
   }

StockQuoteView.xaml (Просмотреть)

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
    <Window.DataContext>
        <local:StockQuoteViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <DataTemplate x:Key="listBoxDateTemplate">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Symbol}"/>
                <TextBlock Text="{Binding Price}"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemTemplate="{StaticResource listBoxDateTemplate}" ItemsSource="{Binding Quotes}"/>
    </Grid>
</Window>

И тогда у вас будет какой-то сервис, который будет снабжать ObservableCollection новыми StockQuotes.

У меня такой вопрос: в этом типе сценария StockQuote считается моделью, и мы представляем ее представлению через ObservableCollection ViewModel. Что в основном означает, что наше представление обладает знаниями о модели. Разве это не нарушает всю парадигму M-V-VM? Или я что-то здесь упускаю ....?

Ответы [ 6 ]

8 голосов
/ 15 апреля 2010

Я больше знаком с MVC, чем с MVVM, но общепринято, что представление будет знать модель. Пока Модель не знает о Представлении, это нормально.

Если это действительно является проблемой по какой-либо причине, проверьте дизайн «Пассивное представление», где представление не знает ничего, кроме необработанных данных, подаваемых в него.

7 голосов
/ 15 апреля 2010

В MVVM модель представления - это нечто среднее между представлением и моделью, которое предоставляет данные из модели таким образом, что представление может быть легко обработано представлением. В строгом приложении MVVM представление не знает о модели, только о модели представления.

В вашем конкретном примере модель представления должна называться не StockQuoteViewModel, а StockQuotesViewModel (учитывайте множественное число), потому что модель представления отображает множество биржевых котировок с помощью определенной коллекции пользовательского интерфейса, которая легко обрабатывается представлением (потому что ObservableCollection<T> реализует INotifyCollectionChanged<T>). Тип элементов в коллекции должен быть моделью представления (например, StockQuoteViewModel), которая предоставляет данные из одного объекта StockQuote. В такой модели представления вы можете добавить логику, такую ​​как добавление $ -символа к Price и так далее.

Часто проще представить некоторые объекты модели в модели представления, но правильным способом было бы создать модель представления для каждого класса модели.

С наилучшими пожеланиями,
Оливер Ханаппи

3 голосов
/ 15 апреля 2010

Проверьте видео: Джейсон Долингер на MVVM . Он ответит на ваш вопрос.

Также см. Вопрос SO wpf mvvm путаница для дополнительных ресурсов.

3 голосов
/ 15 апреля 2010

Нет. Вы не выставляете StockQuote. Вы только указываете (слабо типизированный) интерфейс в представлении. Представление знает только два свойства: Symbol и Price. Вы можете легко заменить StockQuote чем-либо еще, если он реализует их.

1 голос
/ 15 апреля 2010

Насколько я понимаю, ViewModels относятся к моделям, а свойства - к полям. Это очень слабая аналогия, но она подразумевает, что вы не изолированы должным образом, если ваш просмотр напрямую обращается к вашей модели. Как и в случае с тривиальными свойствами в классе, обертывающем частные поля, вы получаете много дублирования и шаблонного кода при переносе соответствующих свойств модели в свойствах ViewModel для использования представлением. Это то, что беспокоит меня из-за этого паттерна, и я до сих пор не решил, стоят ли выгоды от раздувания.

В этом конкретном примере, я думаю, было бы излишне создавать виртуальную машину для каждого экземпляра StockQuote, поскольку вы, вероятно, не выполняете какой-либо существенной логики для представления, представляющего отдельный StockQuote. Я думаю, что в этих небольших случаях гораздо проще и проще обслуживать, просто привязывать к классу Model напрямую. Создание виртуальной машины для небольшого случая уменьшило бы связность, но это также увеличило бы сложность, и я думаю, что это вызов для каждого конкретного случая относительно того, выгодно ли это.

0 голосов
/ 15 апреля 2010

Возможно, я ошибаюсь, но не идея модели представления полностью инкапсулировать модель. Например, у вас есть биржевые котировки, открытые для представления, но они должны быть сопоставлены со свойствами, родными для модели представления, которые затем будут привязаны. Это необходимо для «очистки», которая может потребоваться при передаче данных в модель / представление.

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

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