Xaml 为什么要避免WPF MVVM模式中的代码隐藏?
在这篇文章中,作者Josh Smith说: (1) 在设计良好的MVVM体系结构中,大多数视图的codebehind应该是空的,或者最多只包含操纵该视图中包含的控件和资源的代码。(2) 有时还需要在视图的codebehind中编写与ViewModel对象交互的代码,例如挂接事件或调用方法,否则很难从ViewModel本身调用该方法 我的问题是,在第(1)部分,为什么空的codebehind被认为是设计良好的MVVM(听起来空的codebehind总是好的) 编辑:我的问题是,如下所示,为什么像Xaml 为什么要避免WPF MVVM模式中的代码隐藏?,xaml,mvvm,code-behind,Xaml,Mvvm,Code Behind,在这篇文章中,作者Josh Smith说: (1) 在设计良好的MVVM体系结构中,大多数视图的codebehind应该是空的,或者最多只包含操纵该视图中包含的控件和资源的代码。(2) 有时还需要在视图的codebehind中编写与ViewModel对象交互的代码,例如挂接事件或调用方法,否则很难从ViewModel本身调用该方法 我的问题是,在第(1)部分,为什么空的codebehind被认为是设计良好的MVVM(听起来空的codebehind总是好的) 编辑:我的问题是,如下所示,为什么像A
AttachedCommandBehavior
或InvokeCommandAction
这样的方法试图避免代码隐藏编码。
让我详细解释一下
就第(1)项而言,我认为从目前的情况来看,情况如下。由于边框没有为MouseRightButtonDown
实现ICommandSource
,因此通常无法绑定事件和ICommand
,但可以使用
但是,
我们使用下面的XAML及其codebehind的Border\u MouseRightButtonDown
方法,该方法链接到上面提到的(2)Josh Simth
<Border MouseRightButtonDown ="Border_MouseRightButtonDown"/>
我认为如上所述使用codebehind并不坏,因为它们之间的区别仅在于绑定命令或添加事件处理程序的位置
您对此有何看法?我认为引用的部分指的是数据可视化的方式。我认为他们的意思是,您不应该在代码背后编写代码,例如,与数据显示方式或位置相关的代码(例如:
label1.Text=…
)。使用绑定这样做可以更容易地分离设计和代码(如果在更高版本中需要在名为“tbTest”的文本框中显示数据,会发生什么情况?您必须更改代码)
他们并不是说你不应该在代码隐藏中使用任何代码——他们只是说在理想的世界中,你只会对那些本来无法处理的事件或数据做出反应
至少我从你引用的章节中了解到了这一点。代码背后并没有什么本质上的不好之处。对于简单的情况,可以使用它。然而,在许多情况下,UI逻辑很难管理。将该逻辑封装在附加的行为和视图模型中,允许我们隔离变量(并测试它们),以便更容易理解和维护 如果要考虑可测试性,那么可以封装在viewmodels和附加行为中的UI逻辑越多,就越能够在不诉诸UI测试的情况下进行验证。(虽然它没有完全消除UI测试的需要,但它确实在进行UI测试之前提供了第一级验证,这将更加耗费时间/资源 为什么空代码隐藏被认为是设计良好的MVVM 拥有一个代码隐藏文件,该文件在其构造函数中仅包含对InitializeComponent()的调用,这意味着您已经达到了纯度-您的代码隐藏中绝对没有逻辑。您没有用任何理应属于viewmodel或model的代码污染您的视图。这意味着:
- viewmodel(和模型)更易于单独测试
- 您已经实现了良好的松耦合级别,从维护和可扩展性的角度来看,这具有极好的好处
编辑: 让我来回答你的一些问题,我希望这能有所帮助 在我的视图中,viewmodel的(视图模型)角色具有UI逻辑和视图状态 viewmodel中不应包含任何UI逻辑或“视图状态”。出于本说明的目的,我将视图状态定义为滚动位置、选定行索引、选定索引、窗口si
<Border xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseRightButtonDown">
<i:InvokeCommandAction Command="{Binding SomeCommand}"
CommandParameter="A Command on MouseRightButtonDown"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Border>
<Border MouseRightButtonDown ="Border_MouseRightButtonDown"/>