Опубликован: 13.12.2011 | Доступ: свободный | Студентов: 1021 / 34 | Оценка: 4.29 / 4.57 | Длительность: 13:56:00
Лекция 9:

Применение паттерна MVVM как оптимального при проектировании WPF и Silverlight приложений

Подтверждение правильности данных и сообщение об ошибках

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

Silverlight и WPF оказывают поддержку для управления ошибками подтверждения правильности данных, которые происходят, когда изменяются отдельные свойства, связанные с элементами управления в представлении. Для отдельных свойств, которые связываются с элементом управления, модель представления или модель могут сигнализировать ошибку подтверждения правильности данных в пределах метода set свойства, отклоняя входящее плохое значение и выдавая исключение. Если свойство ValidatesOnExceptions на привязке данных будет равно true, то механизм привязки данных в WPF и Silverlight обработает исключение и покажет пользователю визуальный индикатор, что есть ошибка правильности данных.

Однако, выдачу исключений свойствами таким образом нужно избегать, где только возможно. Альтернативный подход должен реализовать интерфейсы IDataErrorInfo или INotifyDataErrorInfo (данный интерфейс рассматриваться не будет, в связи с тем, что он поддерживается в настоящий момент только в Silverlight 4 и не доступен в WPF 4 и, как следствие, его применение в синхронной разработке двух типов приложения является не столь актуальным) в классах модели представления или модели. Эти интерфейсы позволяют модели представления или модели выполнять проверку правильности данных для значений одного или более свойств и возвращать сообщение об ошибке представлению так, чтобы пользователь мог быть уведомлен об ошибке.

Реализация IDataErrorInfo

Интерфейс IDataErrorInfo предоставляет базовую поддержку валидации данных и сообщения об ошибках. Он определяет два свойства только для чтения: свойство индексатора, с названием свойства в качестве параметра индексатора, и свойство Error. Оба свойства возвращают строковое значение.

Свойство индексатора позволяет модели представления или классу модели предоставить сообщение об ошибке, определенное для именованного свойства. Пустая строка или нулевое возвращаемое значение указывают представлению, что измененное значение свойства допустимо. Свойство Error позволяет модели представления или классу модели предоставить сообщение об ошибке для всего объекта. Отметьте, что это свойство в настоящий момент не вызывается механизмом привязки данных Silverlight или WPF.

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

Когда, привязывая элементы управления в представлении к свойствам, вы хотите проверить их через интерфейс IDataErrorInfo, установите свойство ValidatesOnDataErrors в привязке данных в true. Это гарантирует, что механизм привязки данных запросит информацию об ошибке из связанного свойства.

<TextBox
    Text="{Binding Path=Currentemployee.Name, Mode=TwoWay, 
    ValidatesOnDataErrors=True, NotifyOnValidationError=True }"
/>

Создание и соединение

Паттерн MVVM помогает вам чисто отделить UI от представления, бизнес-логики и данных, поэтому реализация правильного кода в правильном классе является важным первым шагом в эффективном использовании паттерна MVVM. Управление взаимодействием между классами модели представления и представления посредством привязки данных и команд является также важным аспектом для рассмотрения. Следующий шаг рассмотрит, как представление, модель представления, и классы модели инстанцируются и связываются друг с другом во время выполнения.

Выбор правильной стратегии для этого шага особенно важен, если вы используете контейнер внедрения зависимостей в своем приложении. Managed Extensibility Framework (MEF) обеспечивает возможность определять зависимости между представлением, моделью представления, и классами модели и выполнить их контейнером. Более детально применение MEF рассматривается в следующих лекциях.

Как правило, есть непосредственное отношение между представлением и его моделью представления. Модель представления и представление слабо связаны через свойство контекста данных представления. Это позволяет визуальным элементам и поведениям в представлении быть связанными со свойствами, командами, и методами модели представления. Вы должны будете решить, как управлять инстанцированием классов модели представления и представления и их ассоциации через свойство DataContext во время выполнения.

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

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

Создание модели представления через XAML

Возможно, самый простой подход для представления – это декларативно инстанцировать его соответствующую модель представления в XAML. Когда представление будет создано, также будет создан соответствующий объект модели представления. Можно также задать в XAML, что модель представления будет установлена как контекст данных представления.

<UserControl.DataContext>
    <my:MyViewModel/>
</UserControl.DataContext>

Этот подход требует, чтобы у вашей модели представления был конструктор по умолчанию (без параметров).

У декларативного создания и присвоения модели представления представлением есть преимущество в том, что он прост и хорошо работает в инструментах времени проектирования, таких как Microsoft Expression Blend или Microsoft Visual Studio. Недостаток этого подхода в том, что у представления есть знание о соответствующей модели представления.

Создание модели представления программно

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

public MyView()
{
    InitializeComponent();
    this.DataContext = new MyViewModel();
}

У программируемого создания и присвоения модели представления в пределах code-behind представления есть преимущество в том, что этот способ прост и хорошо работает в инструментах времени проектирования как Expression Blend или Visual Studio. Недостаток этого подхода в том, что представление должно знать о соответствующем типе модели представления, и что он требует кода в code-behind представления. Используя контейнер внедрения зависимости, такой как MEF, можно обеспечить слабую связь между моделью представления и представлением.

Создание представления, определенного как шаблон данных

Представление может быть определено как шаблон данных и связано с типом модели представления. Шаблоны данных могут быть определены как ресурсы, или могут быть определены как встроенные, в пределах элемента управления, который отображает модель представления. "Контент" элемента управления является экземпляром модели представления, и шаблон данных используется для её визуального представления. WPF и Silverlight автоматически инстанцируют шаблон данных и установят его контекст данных в экземпляр модели представления во время выполнения. Этот метод является примером ситуации, в которой в начале инстанцируют модель представления, а уже потом – представление.

Шаблоны данных гибки и легковесны. Разработчик UI может использовать их, чтобы легко определить визуальное представление модели представления, без какого-либо сложного кода. Шаблоны данных ограничиваются представлениями, которые не требуют никакой логики UI (code-behind). Для визуальной разработки и редактирования шаблонов данных может использоваться Microsoft Expression Blend.

Следующий пример показывает ItemsControl, который связан со списком клиентов. Каждый объект потребителя в базовой коллекции является экземпляром модели представления. Представление для клиента определяется встроенным шаблоном данных. В следующем примере представление для каждой потребительской модели представления состоит из StackPanel с меткой и текстовым полем, связанным со свойством Name модели представления.

<ItemsControl ItemsSource="{Binding Customers}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
               <TextBlock VerticalAlignment="Center" Text="Customer Name: "/>
               <TextBox Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Можно также задать шаблон данных как ресурс. Следующий пример показывает шаблон данных, определённый как ресурс и применённый к элементу управления через расширение разметки StaticResource.

<UserControl ...>
    <UserControl.Resources>
        <DataTemplate x:Key="CustomerViewTemplate">
            <local:CustomerContactView />
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ContentControl
             Content="{Binding Customer}"
             ContentTemplate="{StaticResource CustomerViewTemplate}">
    </Grid>
</Window>

Здесь шаблон данных обертывает конкретный тип представления. Это позволяет представлению определять поведение code-behind. Таким образом, шаблонный механизм данных может использоваться для того, чтобы поверхностно предоставить связи между представлением и моделью представления. Хотя предыдущий пример показывает шаблон в ресурсах UserControl, его часто помещают в ресурсы приложения для повторного использования.

Краткие итоги

WPF/Silverlight может предложить разработчикам приложений очень многое, нужно начать мыслить немного иначе, чтобы научиться пользоваться этими возможностями. Шаблон MVVM — простой и эффективный набор рекомендаций для проектирования и реализации приложений WPF/Silverlight. Он позволяет разделять данные, поведение и представление.

Набор для практики

Вопросы:

  1. Паттерн MVVM и его предназначение.
  2. Альтернативные решения паттерна MVVM.
  3. Роль модели в паттерне MVVM.
  4. Роль представления в паттерне MVVM.
  5. Роль модели представления в паттерне MVVM.