Реализовать интерфейс с шаблоном WPF MVVM - PullRequest
0 голосов
/ 12 января 2012

Я хочу реализовать интерфейс (добавить поведение) для набора пользовательских контролей WPF. Я использую шаблон проектирования MVVM. Где я должен реализовать интерфейс? в коде управления пользователя позади или в классе модели View?

Ex:

Мой интерфейс

interface IWizard
{
    event RoutedEventHandler MoveNext;
    event RoutedEventHandler MoveBack;
    event RoutedEventHandler Cancelled;   

    bool IsLast;
    bool IsFirst;
}

Теперь в другом месте я хочу получить доступ к пользовательским элементам управления, которые реализовали этот интерфейс как этот.

 ((IWizard)userControl).MoveNext += ...
 ((IWizard)userControl).MoveBack += ...
 ((IWizard)userControl).IsLast = true; 

и т.д ..

Реализация в коде UserControl позади

Я не могу получить доступ к свойствам / методам интерфейса непосредственно в модели представления. Я должен связать их вручную. верно?


PS: в этом примере я хочу привязать (TwoWay Bind) IsLast Свойство с видимостью кнопки.

Реализация в модели класса View

Я не могу получить доступ к usercontrol как к объекту интерфейса. например: ((IWizard)userControl).MoveNext += ...

Какова лучшая практика по реализации интерфейса в Usercontrol с шаблоном проектирования MVVM?

Ответы [ 4 ]

6 голосов
/ 12 января 2012

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

Я знаю, что вы не сможете получить доступ к свойствам непосредственно в модели представления, но для этого и нужен MVVM.Используйте привязки и команды для привязки свойств и методов из Control к вашей ViewModel

4 голосов
/ 12 января 2012

В совершенном мире MVVM ViewModel ничего не знает о View.Реализует ли View какой-либо интерфейс вообще, не имеет значения с точки зрения ViewModel.

В вашем сценарии я считаю более важным, кто будет реагировать на события MoveNext, MoveBack и Canceled.Скорее всего, это будет ViewModel.Что это означает, что вы, вероятно, могли бы использовать такие методы, как WizardMoved(object sender, EventArgs e) в этих ViewModels.Посмотрите, что мы здесь сделали - ViewModel должен иметь какие-то косвенные знания о View.Это плохой знак.

Возможно, вместо этого вы могли бы подойти к проблеме по-другому.Возможно, вам нужен интерфейс IWizardMovement, который определит методы для обработки событий перемещения мастера - и этот интерфейс будет реализован ViewModels.Поэтому, когда вы передаете ViewModel в View, он может легко подписать обработчики ViewModel на свои собственные события (обратите внимание, что на самом деле не имеет значения, какой интерфейс реализует View).

public interface IWizardMovementViewModel
{
    void WizardMovedNext(object sender, EventArgs e);
    void WizardMovedBack(object sender, EventArgs e);
    void WizardMoveCanceled(object sender, EventArgs e);
}

Теперь, так как в MVVM Viewзнает о ViewModel (и никак иначе), вы можете легко использовать это знание:

// Wizard user control constructor
public Wizard(IWizardMovementViewModel viewModel)
{
    MoveNext += viewModel.WizardMovedNext;
    MoveBack += viewModel.WizardMovedBack;
    Canceled += viewModel.WizardMoveCanceled;
}

ViewModel теперь отделен от View навсегда, и то, как выглядит ваш View, уже не важно (так какникогда не должен был быть на первом месте).

3 голосов
/ 12 января 2012

Добавьте свойство IsLast в ViewModel, убедитесь, что оно правильно вызывает NotifyPropertyChanged.

Свяжите видимость кнопки со свойством IsLast, используя ValueConverter, который преобразует логическое значение в Visability и обратно.

Готово.

3 голосов
/ 12 января 2012

Прежде всего, ваша модель представления не должна иметь поля с именем "userControl".

Когда вы разрабатываете приложение MVVM, вы должны думать о слоях.Слой модели должен использоваться сам по себе.Слой View-Model можно использовать с моделями и сервисами.Представление - это то, что объединяет все воедино.

А как насчет навигации?

Вместо того, чтобы предоставить вашей модели представления прямой доступ к пользовательскому элементу управления, вы должны только дать емуДоступ к абстрактному понятию навигации.В WPF это означает NavigationWindow.NavigationService или Frame.NavigationService.

Пример этого можно увидеть в классе NavigationViewModel в Granite.Xaml (http://granite.codeplex.com/SourceControl/changeset/view/85060#2109525)., поскольку он использует абстрактный интерфейс (в моем случае INavigator, IWizard вваш) вы все еще можете протестировать модель представления в отдельности, используя простые приемы насмешки.

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