使用MVVM模式处理控件上的鼠标事件 - 最佳实践 -

时间:2020-12-11 20:17:21

I found actually 2 ways to handle mouse events on controls with the mvvm pattern.

我发现实际上有两种方法可以使用mvvm模式处理控件上的鼠标事件。

Both ways are actually 1 way:

两种方式实际上都是一种方式:

MVVM Light Toolkit by http://mvvmlight.codeplex.com/

MVVM Light Toolkit http://mvvmlight.codeplex.com/

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
        <cmd:EventToCommand
            Command="{Binding SelectionChangedCommand}"
            CommandParameter="{Binding SelectedItems,
                ElementName=MyDataGrid}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

and the Blend interactivity.dll with Behaviours

和Blend interactivity.dll与行为

<i:Interaction.Triggers>
  <i:EventTrigger EventName=”MouseLeftButtonDown”>
    <Behaviours:ExecuteCommandAction Command=”{Binding MyCommand}” CommandParameter=”{Binding MyCommandParameter}”/>
  </i:EventTrigger>
</i:Interaction.Triggers>

Do you know of any better method?

你知道更好的方法吗?

Moderator: Why the heck are my last 6 xaml lines of code not visible at all? They are swallowed by IE and Iron browser. Would you please report the admin to fix that code script? its not working at all very often. prove: http://img251.imageshack.us/img251/5236/errorxt.png

主持人:为什么我的最后6个xaml代码行根本不可见?它们被IE和Iron浏览器吞噬。您能否报告管理员修复该代码脚本?它经常不起作用。证明:http://img251.imageshack.us/img251/5236/errorxt.png

3 个解决方案

#1


7  

Those are both good ways to do it if you need to handle MouseDown in arbitrary places.

如果你需要在任意位置处理MouseDown,这些都是很好的方法。

However these situations generally are few and far between. Usually there is a simpler way:

然而,这些情况通常很少见。通常有一种更简单的方法:

  • Are you sure your objects aren't really buttons that just don't look like buttons? If so, make them real Button objects and template them to look the way you want.
  • 你确定你的对象不是真的按钮看起来不像按钮吗?如果是这样,请将它们设为真正的Button对象,并将它们模板化为您想要的样子。

  • Are you sure your objects are just selection areas for objects in a list? If so, change the container from ItemsControl to ListBox and restyle ListBoxItem to use the selection areas.
  • 您确定您的对象只是列表中对象的选择区域吗?如果是这样,将容器从ItemsControl更改为ListBox并重新设置ListBoxItem以使用选择区域。

  • Are your objects graphical paths that are being selected? Use a ToggleButton whose content is the path itself.
  • 你的对象是被选中的图形路径吗?使用ToggleButton,其内容是路径本身。

There are many other examples of this. In fact, it is uncommon to find a situation in which a MouseDown maps to a Command and there isn't a cleaner way to do the same thing.

还有很多其他例子。实际上,很少发现MouseDown映射到Command的情况,并且没有更简洁的方法来执行相同的操作。

#2


6  

There is always another option. You can handle WPF events in the code-behind of the View and call the appropriate method on the ViewModel. The MVVM pattern doesn't forbid to write any code in the code-behind file of the View.

总有另一种选择。您可以在View的代码隐藏中处理WPF事件,并在ViewModel上调用适当的方法。 MVVM模式不禁止在View的代码隐藏文件中编写任何代码。

The ViewModel sample application of the WPF Application Framework (WAF) shows how this can work.

WPF应用程序框架(WAF)的ViewModel示例应用程序显示了它的工作原理。

#3


1  

XCommand Open source codeplex project has better way to deal with this event based Command/CommandParameter binding. Find here, xcommand.codeplex.com

XCommand开源codeplex项目有更好的方法来处理这个基于事件的Command / CommandParameter绑定。在这里找到xcommand.codeplex.com

Here is the sample code below:

以下是示例代码:

<Grid>
    <TextBlock Margin="20,30,20,0" VerticalAlignment="Top" Height="80" x:Name="XTextBlock"
           Foreground="{Binding FgColor, Mode=TwoWay}"
           XCmd:MouseMove.Command="{Binding TextBlockPointerMovedCommand}"
           XCmd:MouseLeftButtonDown.Command="{Binding TextBlockPointerPressedCommand}"
           XCmd:MouseLeave.Command="{Binding TextBlockPointerExitedCommand}"    
           Text="{Binding Description, Mode=TwoWay}">
    </TextBlock>
    <Grid Grid.Column="1" Background="{Binding BgColor, Mode=TwoWay}"
          XCmd:MouseMove.Command="{Binding GridPointerMovedCommand}" 
          XCmd:MouseMove.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
          XCmd:MouseLeftButtonDown.Command="{Binding GridPointerPressedCommand}"
          XCmd:MouseLeftButtonDown.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
          >
    </Grid>
</Grid>

Hope this will be helpful.

希望这会有所帮助。

#1


7  

Those are both good ways to do it if you need to handle MouseDown in arbitrary places.

如果你需要在任意位置处理MouseDown,这些都是很好的方法。

However these situations generally are few and far between. Usually there is a simpler way:

然而,这些情况通常很少见。通常有一种更简单的方法:

  • Are you sure your objects aren't really buttons that just don't look like buttons? If so, make them real Button objects and template them to look the way you want.
  • 你确定你的对象不是真的按钮看起来不像按钮吗?如果是这样,请将它们设为真正的Button对象,并将它们模板化为您想要的样子。

  • Are you sure your objects are just selection areas for objects in a list? If so, change the container from ItemsControl to ListBox and restyle ListBoxItem to use the selection areas.
  • 您确定您的对象只是列表中对象的选择区域吗?如果是这样,将容器从ItemsControl更改为ListBox并重新设置ListBoxItem以使用选择区域。

  • Are your objects graphical paths that are being selected? Use a ToggleButton whose content is the path itself.
  • 你的对象是被选中的图形路径吗?使用ToggleButton,其内容是路径本身。

There are many other examples of this. In fact, it is uncommon to find a situation in which a MouseDown maps to a Command and there isn't a cleaner way to do the same thing.

还有很多其他例子。实际上,很少发现MouseDown映射到Command的情况,并且没有更简洁的方法来执行相同的操作。

#2


6  

There is always another option. You can handle WPF events in the code-behind of the View and call the appropriate method on the ViewModel. The MVVM pattern doesn't forbid to write any code in the code-behind file of the View.

总有另一种选择。您可以在View的代码隐藏中处理WPF事件,并在ViewModel上调用适当的方法。 MVVM模式不禁止在View的代码隐藏文件中编写任何代码。

The ViewModel sample application of the WPF Application Framework (WAF) shows how this can work.

WPF应用程序框架(WAF)的ViewModel示例应用程序显示了它的工作原理。

#3


1  

XCommand Open source codeplex project has better way to deal with this event based Command/CommandParameter binding. Find here, xcommand.codeplex.com

XCommand开源codeplex项目有更好的方法来处理这个基于事件的Command / CommandParameter绑定。在这里找到xcommand.codeplex.com

Here is the sample code below:

以下是示例代码:

<Grid>
    <TextBlock Margin="20,30,20,0" VerticalAlignment="Top" Height="80" x:Name="XTextBlock"
           Foreground="{Binding FgColor, Mode=TwoWay}"
           XCmd:MouseMove.Command="{Binding TextBlockPointerMovedCommand}"
           XCmd:MouseLeftButtonDown.Command="{Binding TextBlockPointerPressedCommand}"
           XCmd:MouseLeave.Command="{Binding TextBlockPointerExitedCommand}"    
           Text="{Binding Description, Mode=TwoWay}">
    </TextBlock>
    <Grid Grid.Column="1" Background="{Binding BgColor, Mode=TwoWay}"
          XCmd:MouseMove.Command="{Binding GridPointerMovedCommand}" 
          XCmd:MouseMove.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
          XCmd:MouseLeftButtonDown.Command="{Binding GridPointerPressedCommand}"
          XCmd:MouseLeftButtonDown.CommandParameter="{Binding ElementName=XTextBlock, Path=Text}"
          >
    </Grid>
</Grid>

Hope this will be helpful.

希望这会有所帮助。