左键单击WPF上下文菜单

Rel*_*ity 25 wpf contextmenu mvvm mouseleftbuttondown

我有一个WPF应用程序..我在Xaml文件中有一个Image控件.

右键单击此图像,我有一个上下文菜单.

我也想在"左键单击"中显示相同内容.

我如何以MVVM方式执行此操作?

Ben*_*lde 41

这是一个仅限XAML的解决方案.只需将此样式添加到按钮即可.这将导致左右键单击打开上下文菜单.请享用!

<Button Content="Open Context Menu">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Style.Triggers>
                <EventTrigger RoutedEvent="Click">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
                                    <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
                                </BooleanAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem />
                        <MenuItem />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </Button.Style>
</Button>
Run Code Online (Sandbox Code Playgroud)

  • 样式是正确的,但是,当我向MenuItem添加Command时,它不会触发事件.我已经验证 - 绑定是正确的.任何的想法? (11认同)
  • 我与@utkarsh有同样的问题,当我尝试将命令绑定到MenuItem时,`&lt;MenuItem Header =“Download”Command =“{Binding DownloadButtonCommand}”/&gt;`它不起作用,有什么建议吗? (3认同)
  • 似乎只有右键单击才能设置contextmenu的数据绑定.右键单击打开后,它也会在左键单击时起作用.这就是为什么我最终使用这个解决方案:/sf/answers/2038677511/ (2认同)

Fre*_*lad 13

您可以使用像这样的Image的MouseDown事件来完成此操作

<Image ... MouseDown="Image_MouseDown">
    <Image.ContextMenu>
        <ContextMenu>
            <MenuItem .../>
            <MenuItem .../>
        </ContextMenu>
    </Image.ContextMenu>
</Image>
Run Code Online (Sandbox Code Playgroud)

然后在代码后面的EventHandler中显示ContextMenu

private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
    if (e.ChangedButton == MouseButton.Left)
    {
        Image image = sender as Image;
        ContextMenu contextMenu = image.ContextMenu;
        contextMenu.PlacementTarget = image;
        contextMenu.IsOpen = true;
        e.Handled = true;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 此实现导致上下文菜单出现并立即消失.我在DataTemplate中使用控件及其上下文菜单,不确定是否重要... (6认同)

小智 8

You can invent your own DependencyProperty which opens a context menu when image is clicked, just like this:

  <Image Source="..." local:ClickOpensContextMenuBehavior.Enabled="True">
      <Image.ContextMenu>...
      </Image.ContextMenu>
  </Image>
Run Code Online (Sandbox Code Playgroud)

And here is a C# code for that property:

public class ClickOpensContextMenuBehavior
{
  private static readonly DependencyProperty ClickOpensContextMenuProperty =
    DependencyProperty.RegisterAttached(
      "Enabled", typeof(bool), typeof(ClickOpensContextMenuBehavior),
      new PropertyMetadata(new PropertyChangedCallback(HandlePropertyChanged))
    );

  public static bool GetEnabled(DependencyObject obj)
  {
    return (bool)obj.GetValue(ClickOpensContextMenuProperty);
  }

  public static void SetEnabled(DependencyObject obj, bool value)
  {
    obj.SetValue(ClickOpensContextMenuProperty, value);
  }

  private static void HandlePropertyChanged(
    DependencyObject obj, DependencyPropertyChangedEventArgs args)
  {
    if (obj is Image) {
      var image = obj as Image;
      image.MouseLeftButtonDown -= ExecuteMouseDown;
      image.MouseLeftButtonDown += ExecuteMouseDown;
    }

    if (obj is Hyperlink) {
      var hyperlink = obj as Hyperlink;
      hyperlink.Click -= ExecuteClick;
      hyperlink.Click += ExecuteClick;
    }
  }

  private static void ExecuteMouseDown(object sender, MouseEventArgs args)
  {
    DependencyObject obj = sender as DependencyObject;
    bool enabled = (bool)obj.GetValue(ClickOpensContextMenuProperty);
    if (enabled) {
      if (sender is Image) {
        var image = (Image)sender;
        if (image.ContextMenu != null)
          image.ContextMenu.IsOpen = true;
      }
    }
  } 

  private static void ExecuteClick(object sender, RoutedEventArgs args)
  {
    DependencyObject obj = sender as DependencyObject;
    bool enabled = (bool)obj.GetValue(ClickOpensContextMenuProperty);
    if (enabled) {
      if (sender is Hyperlink) {
        var hyperlink = (Hyperlink)sender;
        if(hyperlink.ContextMenu != null)
          hyperlink.ContextMenu.IsOpen = true;
      }
    }
  } 
}
Run Code Online (Sandbox Code Playgroud)

  • 这非常有用,但我需要将“ContextMenu”的“PlacementTarget”分配回“DependencyObject”(在我的例子中是“Button”),以便菜单正确填充。这是为“ListView”中的每个项目填充的动态上下文菜单。 (3认同)