Jin*_*ung 47 xaml code-behind mvvm
在文章中,使用Model-View-ViewModel设计模式的WPF应用程序,Josh Smith的作者说:
(1)在设计良好的MVVM体系结构中,大多数视图的代码隐藏应该是空的,或者最多只包含操作该视图中包含的控件和资源的代码.(2)有时还需要在与ViewModel对象交互的View的代码隐藏中编写代码,例如挂钩事件或调用一个本来很难从ViewModel本身调用的方法.
我的问题是,在(1),为什么空代码被认为是一个设计良好的MVVM.(听起来空的代码隐藏总是很好.)
编辑:我的问题是,如下,为什么像的方法AttachedCommandBehavior或者InvokeCommandAction是试图避免代码隐藏编码.
让我解释一下细节.
就(1)而言,我会认为以下情况来自AttachedCommandBehavior.由于Border没有实现ICommandSourcefor MouseRightButtonDown,你不能通常绑定事件和ICommand,但可以使用AttachedCommandBehavior.
<!-- I modified some code from the AttachedCommandBehavior to show more simply -->
<Border>
<local:CommandBehaviorCollection.Behaviors>
<local:BehaviorBinding Event="MouseRightButtonDown"
Command="{Binding SomeCommand}"
CommandParameter="A Command on MouseRightButtonDown"/>
</local:CommandBehaviorCollection.Behaviors>
</Border>
Run Code Online (Sandbox Code Playgroud)
要么
我们可以这样做System.Windows.Interactivity.InvokeCommandAction.
<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>
Run Code Online (Sandbox Code Playgroud)
但,
我们使用以下XAML及其代码隐藏Border_MouseRightButtonDown方法,该方法与上述(2)Josh Simth相关联.
<Border MouseRightButtonDown ="Border_MouseRightButtonDown"/>
Run Code Online (Sandbox Code Playgroud)
我认为使用上面的代码隐藏并不坏,只是因为它们之间的区别只是绑定命令或添加事件处理程序.
你怎么看待这件事?
slu*_*ter 68
为什么空代码被视为精心设计的MVVM
拥有一个代码隐藏文件,它只包含在构造函数中调用InitializeComponent(),这意味着你已经达到了纯度 - 你的代码隐藏绝对没有逻辑.您没有使用视图模型或模型中正确属于的任何代码污染您的视图.这意味着一些事情:
当您必须更改UI时,即从使用ListView切换到DataGrid,或者从使用标准Microsoft控件更改为使用其他某些供应商时,这些好处确实变得显而易见.
如上所述,有时候在代码隐藏文件中避免使用一些代码是不可能的.你应该确保的是你所拥有的代码纯粹是与UI相关的.例如,如果您有ComboA和ComboB,并且ComboB是为了响应ComboA中的选择而设置的,那么从视图中设置ComboB的SelectedIndex就可以了,但是设置ComboB的Items或SelectedItem不是 - 那些属性是两个数据相关,应通过绑定到viewmodel来指定.SelectedIndex属性直接与视觉相关,并且在某种程度上与实际数据无关(并且与viewmodel无关).
如果您确实从视图中的代码隐藏访问viewmodel,您应该尝试通过接口进行操作.这意味着您的viewmodel作为接口注入或提供给视图.(请注意,绑定子系统不知道或不关心接口,它将继续以正常方式绑定.这实现了更好的代码,耦合更少紧密).我编写它的方式,viewmodel不知道视图存在,并且视图只知道viewmodel作为接口.
但要记住的一件事是MVVM是一种模式,而模式只是在某种情况下实现某种结果的一种方法或处方.它不应该被视为一种宗教,非信徒或非信仰者会去一些炼狱(虽然如果你想避免维护地狱和代码气味的炼狱,坚持这种模式是好的).
如果你想要一个关于这个特定模式如何帮助的一个很好的例子,尝试在ASP.Net中编写一些相当复杂的屏幕,然后在WPF或Silverlight中编写相同的内容,并注意区别.
编辑:
让我回答你的一些问题,我希望它有所帮助....
在我看来,viewmodel的(视图模型)角色具有UI逻辑和视图状态
视图模型中不应该包含任何UI逻辑或"视图状态".出于解释的目的,我将视图状态定义为滚动位置,选定行索引,选定索引,窗口大小等.这些都不属于viewmodel; 像SelectedIndex这样的东西特定于UI中显示数据的方式(如果你改变DataGrid的排序顺序,那么SelectedIndex可以改变,即使SelectedItem仍然是相同的).在这种特殊情况下,SelectedItem可以绑定到viewmodel,但SelectedIndex不应该绑定.
如果你需要跟踪UI会话类型信息,那么你应该提出一些通用的东西(例如,我之前通过将重要的东西保存到KeyValuePair列表中来保持视图状态)然后通过调用"保存"来保存它. viewmodel(通过我之前提到的界面).视图不知道如何保存数据,并且视图模型不知道数据来自视图(它只是通过其接口公开了一个调用).
并且视图的角色是显示一些内容并同步视图模型(具有数据绑定代码)
是的,视图的职责是直观地显示视图模型提供的数据.viewmodel从模型中获取数据(模型负责进行数据库调用或WCF webservice调用,这通常通过"服务"完成,但这是另一个讨论).视图模型然后可以对数据进行整形或操纵,即它可以获得所有客户的列表,但是仅在公共属性中公开该列表的过滤版本(可能是当前客户),然后该视图可以绑定到该公共属性.
如果要将数据操作为可视化的东西(常见示例是将枚举值转换为颜色),则视图模型仍然只具有枚举值,并且视图仍然绑定到该值,但视图还使用转换器将纯数据转换为可视化表示.通过使用转换器,viewmodel仍然避免做任何与UI相关的事情,并且视图避免了任何真实的逻辑.
代码隐藏没有本质上的坏处。对于简单的情况,拥有它很好。但是,在许多情况下,UI逻辑可能变得难以管理。将该逻辑封装在附加的行为和视图模型中,使我们能够隔离变量(并对其进行测试),从而更易于理解和维护。
如果需要考虑可测试性,则可以在视图模型和附加行为中封装的UI逻辑越多,无需借助UI测试就可以验证的逻辑越多。(虽然它并不能完全消除对UI测试的需求,但它确实提供了进行UI测试之前的第一级验证,这将花费更多的时间/资源。
| 归档时间: |
|
| 查看次数: |
27493 次 |
| 最近记录: |