【问题标题】:How Can I Add a New Command to a Control's Event如何向控件的事件添加新命令
【发布时间】:2010-04-21 10:59:18
【问题描述】:

感谢您查看这个问题。

我一直在按照 Josh Smith 的 MVVM 模式示例构建应用程序 (VB/WPF):Click here to view

我的视图具有在事件(例如按钮单击)时触发命令的控件,这些控件绑定到 ViewModel 中的属性。

我的 ViewModel 公开了调用适当方法的 ICommand 类型的属性。

到目前为止,这一直运作良好!我现在想使用拇指控件来允许用户在画布中移动对象。我不相信 Thumb 具有“开箱即用”的命令能力。 Thumb 在移动时会引发“DragDelta”事件。所以我的问题如下:

请问如何扩展控件的能力以根据事件发出命令?

我希望发出一个新命令,比如说“onDragDelta”,这样我就可以将它绑定到我的 ViewModel 中的一个属性,就像我的按钮一样。

非常感谢

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    您想要的是根据 FrameworkElement 的 RoutedEvent 在 ViewModel 中触发 ICommand。不幸的是,WPF 不支持这种“开箱即用”。一些可能性:

    1) 对于 Expression Blend 3,有 Microsoft.Expression.Interactivity.dll,它允许这样做。有关如何执行此操作的示例,请参阅 WPF : Blend 3 Interactions / Behaviours

    2) 您可以在代码隐藏中有一个事件处理程序,它直接调用适当的 ViewModel 命令。例如:

    private void FrameworkElement_DragDelta(object sender, EventArgs e)
    {
        this.MyViewModel.OnDragDelta(sender, e);
    }
    

    3) 作为Cinch 框架的一部分,有一个attached command behaviour。这样,您不必更改代码隐藏。例如:

    Cinch:SingleEventCommand.RoutedEventName="DragDelta"
    Cinch:SingleEventCommand.TheCommandToRun="{Binding Path=DragDeltaCommand}"
    

    请注意,这会调用 ICommand 并将对象(实际上是 SCommandArgs)作为命令参数传递。要在命令处理程序中获取实际的路由事件参数,请执行以下操作:

    var sargs = args as SCommandArgs;
    if (sargs == null)
    {
        return;
    }
    
    var routedEventArgs = sargs.EventArgs as RoutedEventArgs; // Or whatever arguments you actually expect
    if (routedEventArgs == null)
    {
        return;
    }
    
    // Do something here with the event arguments
    

    编辑:也看看Binding Commands to Events?

    【讨论】:

    • 感谢丹尼尔的建议。我首先在后面的代码中处理 Thumb 的“DragDelta”事件,并将该事件的 Horizo​​ntalChanged 和 VerticalChanged 值绑定到我的 ViewModel 中的属性。然后我将 Thumb 的 Canvas.Left 和 Canvas.Top 属性绑定到我的 ViewModel。简单而整洁,但我觉得有必要删除后面的代码。我认为 Horizo​​ntalChanged 和 VerticalChanged 只能作为 Thumb 的 DragDelta 事件的参数。考虑到这一点,我不确定如何将它们直接绑定到 ViewModel。
    • 如果您只获取数据作为事件参数的一部分,那么您要么必须使用方法(1)或(3),要么有一个小的代码隐藏。顺便说一句,我不认为有一些代码隐藏有什么问题,只要不涉及主要(难以测试)逻辑。
    【解决方案2】:

    我宁愿将 Thumb 的当前位置数据绑定到 ViewModel 中的属性,而不是使用 ICommand。现在,如果位置发生变化,您可以在 ViewModel 中执行一些方法,并将差异作为参数。

    我不知道这是否符合您的需求,但这是我的第一个想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多