使用WPF MVVM模式实现接口

时间:2012-01-12 18:19:36

标签: c# wpf mvvm interface

我想为一组WPF用户控件实现一个接口(添加行为)。 我正在使用MVVM设计模式。 我应该在哪里实现界面?在用户控制代码后面或在View模型类中?

例如:

我的界面

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 Code中实现

我无法直接在视图模型中访问接口的属性/方法。我必须手动链接它们。对吗?


PS:在这个例子中,我想绑定(两个绑定)IsLast属性,并且可以看到一个按钮。

在View模型类中实施

我无法将usercontrol作为Interface对象访问。 例如:((IWizard)userControl).MoveNext += ...

使用MVVM设计模式在Usercontrol上实现接口的最佳实践是什么?

4 个答案:

答案 0 :(得分:6)

您应该在UserControl中实现此接口,因为它与UserControl直接相关,它与ViewModel无关。 View Model用于View和Model之间的业务逻辑和交互。在UI / View上发生的事件不应该直接在ViewModel上执行任何操作。

我知道您无法直接在视图模型中访问属性,但这就是MVVM的用途。使用绑定和命令将Control中的属性和方法绑定到ViewModel

答案 1 :(得分:4)

在完美世界的MVVM中,ViewModel对View没有任何了解。从ViewModel的角度来看,View是否实现任何接口都是无关紧要的。

在您的方案中,我认为更重要的是谁将回复MoveNextMoveBackCanceled事件。最有可能的是,这将是ViewModel。这意味着您可能在这些ViewModel中使用WizardMoved(object sender, EventArgs e)等方法。看看我们在这里做了什么 - 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看起来不再那么重要了(因为它永远不应该在第一位)。

答案 2 :(得分:3)

首先,您的视图模型不应该有一个名为“userControl”的字段。

设计MVVM应用程序时,您应该考虑层次。 Model层应该可以单独使用。 View-Model层可与模型和服务一起使用。视图将所有内容组合在一起。

但导航呢?

您应该只允许它访问抽象的导航概念,而不是让您的视图模型直接访问用户控件。在WPF中,这意味着NavigationWindow.NavigationService或Frame.NavigationService。

您可以在Granite.Xaml(http://granite.codeplex.com/SourceControl/changeset/view/85060#2109525)的NavigationViewModel类中看到此示例。因为它需要一个抽象接口(在我的情况下是INavigator,在你的IWizard中),你仍然可以使用简单的模拟技术单独测试视图模型。

答案 3 :(得分:3)

将IsLast属性添加到ViewModel,确保它正确引发NotifyPropertyChanged。

使用ValueConverter将Button的Visibility绑定到IsLast属性,ValueConverter将布尔值转换为Visability并返回。

完成。