我想为一组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中实现
我无法直接在视图模型中访问接口的属性/方法。我必须手动链接它们。对吗?
IsLast
属性,并且可以看到一个按钮。在View模型类中实施
我无法将usercontrol作为Interface对象访问。
例如:((IWizard)userControl).MoveNext += ...
使用MVVM设计模式在Usercontrol上实现接口的最佳实践是什么?
答案 0 :(得分:6)
您应该在UserControl中实现此接口,因为它与UserControl直接相关,它与ViewModel无关。 View Model用于View和Model之间的业务逻辑和交互。在UI / View上发生的事件不应该直接在ViewModel上执行任何操作。
我知道您无法直接在视图模型中访问属性,但这就是MVVM的用途。使用绑定和命令将Control中的属性和方法绑定到ViewModel
答案 1 :(得分:4)
在完美世界的MVVM中,ViewModel对View没有任何了解。从ViewModel的角度来看,View是否实现任何接口都是无关紧要的。
在您的方案中,我认为更重要的是谁将回复MoveNext
,MoveBack
和Canceled
事件。最有可能的是,这将是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并返回。
完成。