Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
423 views
in Technique[技术] by (71.8m points)

c# - WPF RightClick MouseBinding on release?

How can I enable a mouse binding to the release of the right button? At the moment I have the following code in xaml which is linked to closing the wpf window. The problem here is that because it reacts to the rampup of the click when closing the window it activates a context menu on the desktop.

<MouseBinding Command="Close" MouseAction="RightClick" />
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The MouseBinding does not support mouse up actions, only mouse down actions, so you simply cannot do what you want to do using a MouseBinding. The simplest alternative is a code-behind event handler for the MouseRightButtonUp event on the same element you would have added the MouseBinding as an InputBinding to. But I suspect you are avoiding the event handler approach for your own reasons, but you should clarify if that is your intention.

The remaining option available to use is some form of attached behavior. There are many ways to do this but I'll use the fairly standard System.Windows.Interactivity from Blend behaviors. All you have to do is attach an event trigger for right mouse button up and invoke the close command. Everything you need to do this is in the SDK but unfortunately the feature to invoke a command called InvokeCommandAction doesn't properly support routed commands so I've written an alternative called ExecuteCommand.

Here is some sample markup:

<Grid Background="White">
    <Grid.CommandBindings>
        <CommandBinding Command="Close" Executed="CommandBinding_Executed"/>
    </Grid.CommandBindings>
    <!--<Grid.InputBindings>
        <MouseBinding Command="Close" MouseAction="RightClick"/>
    </Grid.InputBindings>-->
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseRightButtonUp">
            <utils:ExecuteCommand Command="Close"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <StackPanel>
        <TextBox Text="Some Text"/>
    </StackPanel>
</Grid>

Your old method is commented out and the new method is below it.

Here is the code-behind just to hook up the routed command:

    private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
        Close();
    }

Finally, here is the implementation of ExecuteCommand:

public class ExecuteCommand : TriggerAction<DependencyObject>
{
    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(ExecuteCommand), null);

    public object CommandParameter
    {
        get { return (object)GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object), typeof(ExecuteCommand), null);

    public UIElement CommandTarget
    {
        get { return (UIElement)GetValue(CommandTargetProperty); }
        set { SetValue(CommandTargetProperty, value); }
    }

    public static readonly DependencyProperty CommandTargetProperty =
        DependencyProperty.Register("CommandTarget", typeof(UIElement), typeof(ExecuteCommand), null);

    protected override void Invoke(object parameter)
    {
        if (Command is RoutedCommand)
        {
            var routedCommand = Command as RoutedCommand;
            var commandTarget = CommandTarget ?? AssociatedObject as UIElement;
            if (routedCommand.CanExecute(CommandParameter, commandTarget))
                routedCommand.Execute(CommandParameter, commandTarget);
        }
        else
        {
            if (Command.CanExecute(CommandParameter))
                Command.Execute(CommandParameter);
        }
    }
}

If you are not using routed commands but are using say, an MVVM RelayCommand, you can don't need ExecuteCommand and you can use InvokeCommandAction instead.

This example uses behaviors. If you are not familiar with behaviors, install the Expression Blend 4 SDK and add this namespace:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

and add System.Windows.Interactivity to your project.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...