【问题标题】:ViewModel Handling EventsViewModel 处理事件
【发布时间】:2013-08-05 22:22:03
【问题描述】:

我在这里看到一个问题,其中 OP 询问将事件绑定到 ViewModel。基本上 ViewModel 应该代表一个包含来自模型的必要数据的抽象视图,以便视图也可以使用绑定。但是为了能够满足 ViewModel 的所有功能,还必须转换 View 中发生的大多数用例,例如,如果搜索文本框为空,则搜索按钮应显示为灰色。这工作正常,但让我们向游戏添加事件。如果 Button.Click 可绑定到 ViewModel 中的 EventHandler 和事件处理程序内部,那么您将能够使用模型对象,这将更容易。

现在我的问题是,既然 WPF 支持事件驱动编程,为什么不能在 ViewModel 中处理事件?如何提供绑定事件功能?

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    事件处理程序将位于视图的代码隐藏文件中。如果您使用的是 MVVM,那么您需要尽量减少代码隐藏文件中的代码量。

    WPF 支持命令,ICommand 接口包括CanExecute 和Execute 方法。 ICommand 的实现允许在视图模型上实现这些方法。

    话虽如此,指挥也有其局限性,所以you should consider using an MVVM framework when using MVVM。 Caliburn.Micro 之类的东西带有 Actions,它还允许基于控制事件调用视图模型上的动词。

    【讨论】:

    • 你是对的。 Action 和类似的东西还有其他框架,但仍然如此。很常见的是,一旦您单击一个按钮,您就需要模型中的一些额外信息来进行某些验证或类似的事情,如果您使用附加属性或附加命令来完成那个小任务,这听起来有点像一种解决方法。而这一切只是因为绑定事件不起作用。
    • 绑定事件确实有效,但正如我所说的,处理程序将位于视图的代码后面。 MVVM 是一种可在 WPF 中实现的设计模式,但这需要一些开箱即用的实现。因此,强烈建议您使用 MVVM 框架,以避免尝试以极高的标准重新实现已经完成的工作。 MVVM 框架不仅解决了指挥问题,还解决了如果您尝试单独实施 MVVM 时将面临的一系列问题。
    • 你能提供几个链接吗?以防万一有人在互联网上偶然发现这个问题。
    • 最好的链接是由 CSLA 业务对象框架的开发者 Rocky Lhotka 提供的链接。
    • 我有一个问题;当您可以使用 Prism 时,为什么选择 Caliburn.Micro?您是否有使用两者的经验。我对 MVVM 比较陌生,并决定从头开始构建我需要的一切。我有很长的路要走,但任务是多余的,为什么要重新发明轮子等。但是,我继续并在没有 MVVM 框架的情况下构建了一个完整的 MVVM 应用程序。不用说我再也不会这样做了,但我学到了很多东西。下次我打算使用 Prism - 但为什么 Caliburn.Micro 比微软自己的品牌好?感谢您的宝贵时间...
    【解决方案2】:

    这是因为事件的使用显式地破坏了 MVVM 模式(我相信您知道)。然而,还有另一种方法 - 使用Attached Command Behaviour pattern。更多信息here。

    可从here 下载小而强大的附加命令框架的代码。

    我希望这会有所帮助。


    编辑。附加行为允许您在不破坏 MVVM 模式的情况下使用事件。用法就像

    <Border Background="Yellow" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2" x:Name="test"> 
        <local:CommandBehaviorCollection.Behaviors>
            <local:BehaviorBinding Event="MouseLeftButtonDown" 
                                   Action="{Binding DoSomething}" 
                                   CommandParameter="An Action on MouseLeftButtonDown"/> 
            <local:BehaviorBinding Event="MouseRightButtonDown" 
                                   Command="{Binding SomeCommand}" 
                                   CommandParameter="A Command on MouseRightButtonDown"/>
        </local:CommandBehaviorCollection.Behaviors> 
        <TextBlock Text="MouseDown on this border to execute the command"/> 
    </Border>
    

    【讨论】:

    • 谢谢。我知道 MVVM 模式我仍然想知道,因为就像我在问题中提到的那样,MVVM 模式意味着保持 View 和 Model 独立,但使用 ViewModel 包含来自 Model 的数据并用其自定义逻辑表示一个抽象 View。现在 View 有了事件,为什么 ViewModel 包含了大部分 View 逻辑,为什么不能在 ViewModel 中处理呢?
    • 因为按照设计,UI 组件或“视图”的事件处理程序必须包含在后面的“视图”代码中——这就是破坏 MVVM 模式的原因。我在上面所说的是你可以拥有你的蛋糕(MVVM)并吃掉它(使用附加的命令)来复制事件处理程序的使用。我将更新我的答案以提供一个使用示例...
    • 我明白了。我不想用代码示例来浪费你的时间。这更多的是讨论。无论如何,命令都很棒,除了您只能在控件上放置一个命令而您可能有 100 个不同的事件,例如。用于文本输入、点击、鼠标悬停。
    • 通过附加命令,您可以将任意数量的事件连接到 ICommand 本身 不会破坏您的 MVVM。看看上面的小例子……
    • 是的,附加的命令可以完成这项工作。我在谈论 wpf 的设计。 :) 感谢您的示例。当我想到附加的命令时,只有这么小的想法让我很恼火。我已经使用它们一段时间了。我想一年前,我意识到触发 Command.Execute 的事件是匿名动态创建的,一旦您更改数据上下文,它们就不会被释放,因此为什么当时我无法正确处置旧的数据上下文对象。
    猜你喜欢
    • 1970-01-01
    • 2010-12-26
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多