MVVM View event Viewmodel command binding

2020-02-14 10:50发布

问题:

I'm looking for a good (read: simple) example on how to implement event aggregators with Prism. I've never used Prism and I'm also quite new to MVVM itself.

I have a WPF canvas as a View and I want to handle the MouseUp event on the canvas in the Viewmodel. Now the powers that be at our organization wants me to use Prism, and apparently Prism recommends using event aggregators, which is why I need a sample to get me started.

回答1:

all you need for this is the EventToCommand behavior from MVVMLight or from System.Windows.Interactivity (Blend SDK). i would recommend you to take the MVVMLight version because it has some usefull specials:)

<Canvas>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="MouseUp" >
        <i:InvokeCommandAction Command="{Binding YourMouseUpViewModelCommand}" />
    </i:EventTrigger>
</i:Interaction.Triggers>
</Canvas>

EventAggregator from Prism i mostly used for decoupled Viewmodel to Viewmodel communication.



回答2:

I didn't know PRISM's EventAggregator allowed for event->command binding.

Another option for you in this case is using a "behavior". Here's a decent overview Behaviors: http://wpftutorial.net/Behaviors.html. You can ignore the Blend part of the tutorial; the important part is that you have at least the Blend 3 SDK installed. Here's how I did this:

public class ButtonDoubleClickCommandBehavior : Behavior<Button>
{
    public ICommand DoubleClickCommand
    {
        get { return (ICommand)GetValue(DoubleClickCommandProperty); }
        set { SetValue(DoubleClickCommandProperty, value); }
    }

    public static readonly DependencyProperty DoubleClickCommandProperty =
        DependencyProperty.Register("DoubleClickCommand", typeof(ICommand), typeof(ButtonDoubleClickCommandBehavior));

    protected override void OnAttached()
    {
        this.AssociatedObject.MouseDoubleClick += AssociatedObject_MouseDoubleClick;
    }

    protected override void OnDetaching()
    {
        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.MouseDoubleClick -= AssociatedObject_MouseDoubleClick;
        }
    }

    void AssociatedObject_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        if (DoubleClickCommand != null && DoubleClickCommand.CanExecute(null))
        {
            DoubleClickCommand.Execute(null);
        }
    }
}

You could add another dependency property to the behavior to bind a command parameter so you can execute the command with that parameter; I just used null in my example.

And my XAML:

<Button Content="{Binding Path=Description}" VerticalAlignment="Center" HorizontalAlignment="Stretch" Template="{StaticResource TextBlockButtonTemplate}" Style="{StaticResource ZynCommandButton}" Tag="DescriptionButton">
    <e:Interaction.Behaviors>
        <ZViewModels:ButtonDoubleClickCommandBehavior DoubleClickCommand="{Binding Path=ItemDescriptionCommand}"/>
    </e:Interaction.Behaviors>
</Button>


回答3:

A more generic way using behaviors is proposed at AttachedCommandBehavior V2 aka ACB and it even supports multiple event-to-command bindings,

Here is a very basic example of use:

<Border local:CommandBehavior.Event="MouseDown"  
        local:CommandBehavior.Command="{Binding DoSomething}"
        local:CommandBehavior.CommandParameter="From the DarkSalmon Border"
/>