WPF 左键单击上下文菜单

发布于 2024-10-05 04:40:46 字数 126 浏览 0 评论 0原文

我有一个 WPF 应用程序..其中我在 Xaml 文件中有一个图像控件。

右键单击该图像,我有一个上下文菜单。

我希望在“左键单击”上也显示相同的内容。

我如何以 MVVM 方式做到这一点?

I have a WPF application..In which I have an Image control in Xaml file.

On right click of this image I have a context menu.

I would like to have same to be displayed on "Left click" also.

How do I do this in MVVM way ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

定格我的天空 2024-10-12 04:40:46

这是仅 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>

Here is a XAML only solution.
Just add this style to your button.
This will cause the context menu to open on both left and right click. Enjoy!

<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>
半窗疏影 2024-10-12 04:40:46

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

<Image ... MouseDown="Image_MouseDown">
    <Image.ContextMenu>
        <ContextMenu>
            <MenuItem .../>
            <MenuItem .../>
        </ContextMenu>
    </Image.ContextMenu>
</Image>

,然后在后面的代码中的 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;
    }
}

You can do this by using the MouseDown event of an Image like this

<Image ... MouseDown="Image_MouseDown">
    <Image.ContextMenu>
        <ContextMenu>
            <MenuItem .../>
            <MenuItem .../>
        </ContextMenu>
    </Image.ContextMenu>
</Image>

And then show the ContextMenu in the EventHandler in code behind

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;
    }
}
七色彩虹 2024-10-12 04:40:46

您可以发明自己的 DependencyProperty,它会在单击图像时打开上下文菜单,如下所示:

  <Image Source="..." local:ClickOpensContextMenuBehavior.Enabled="True">
      <Image.ContextMenu>...
      </Image.ContextMenu>
  </Image>

下面是该属性的 C# 代码:

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;
      }
    }
  } 
}

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>

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;
      }
    }
  } 
}
勿挽旧人 2024-10-12 04:40:46

如果您只想在 Xaml 中执行此操作而不使用代码隐藏,则可以使用 Expression Blend 的触发器支持:

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

<Button x:Name="addButton">
    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding Items}" />
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=addButton, Mode=OneWay}"/>
                <ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="IsOpen" Value="True"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button.ContextMenu>
</Button>

If you want to do this just in Xaml without using code-behind you can use Expression Blend's triggers support:

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

<Button x:Name="addButton">
    <Button.ContextMenu>
        <ContextMenu ItemsSource="{Binding Items}" />
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=addButton, Mode=OneWay}"/>
                <ei:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=addButton}" PropertyName="IsOpen" Value="True"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button.ContextMenu>
</Button>
蓝海 2024-10-12 04:40:46

您只需将代码添加到函数 Image_MouseDown

e.Handled = true;

那么它就不会消失。

you only need add the code into function Image_MouseDown

e.Handled = true;

Then it will not disappear.

天煞孤星 2024-10-12 04:40:46

交互性已经过时,不再支持。新的实施方法是:

 xmlns:b="http://schemas.microsoft.com/xaml/behaviors"

 <Button x:Name="ConvertVideoButton">
            <Button.ContextMenu>
                <ContextMenu VerticalContentAlignment="Top" >
                    <MenuItem Header="Convert  1"  Command="{Binding ConvertMkvCommand}" />
                    <MenuItem Header="Convert 2"  Command="{Binding ConvertMkvCommand}" />
                </ContextMenu>
            </Button.ContextMenu>

            <b:Interaction.Triggers>
                <b:EventTrigger  EventName="Click">
                    <b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=ConvertVideoButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=ConvertVideoButton, Mode=OneWay}"/>
                    <b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=ConvertVideoButton}" PropertyName="IsOpen" Value="True"/>
                </b:EventTrigger>
            </b:Interaction.Triggers>
        </Button>

Interactivity is old and not support any more. The new approach for the implementation is:

 xmlns:b="http://schemas.microsoft.com/xaml/behaviors"

 <Button x:Name="ConvertVideoButton">
            <Button.ContextMenu>
                <ContextMenu VerticalContentAlignment="Top" >
                    <MenuItem Header="Convert  1"  Command="{Binding ConvertMkvCommand}" />
                    <MenuItem Header="Convert 2"  Command="{Binding ConvertMkvCommand}" />
                </ContextMenu>
            </Button.ContextMenu>

            <b:Interaction.Triggers>
                <b:EventTrigger  EventName="Click">
                    <b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=ConvertVideoButton}" PropertyName="PlacementTarget" Value="{Binding ElementName=ConvertVideoButton, Mode=OneWay}"/>
                    <b:ChangePropertyAction TargetObject="{Binding ContextMenu, ElementName=ConvertVideoButton}" PropertyName="IsOpen" Value="True"/>
                </b:EventTrigger>
            </b:Interaction.Triggers>
        </Button>
梦里°也失望 2024-10-12 04:40:46

嘿,我遇到了同样的问题,正在寻找解决方案,但我在这里找不到。

我对 MVVM 一无所知,所以它可能不符合 MVVM,但它对我有用。

第 1 步:为上下文菜单命名。

<Button.ContextMenu>
    <ContextMenu Name="cmTabs"/>
</Button.ContextMenu>

步骤2:双击控制对象并插入此代码。顺序很重要!

Private Sub Button_Click_1(sender As Object, e As Windows.RoutedEventArgs)
        cmTabs.StaysOpen = True
        cmTabs.IsOpen = True
    End Sub

第 3 步:享受

这将对左和右做出反应。右键单击。它是一个带有 ImageBrush 和 ControlTemplate 的按钮。

Hey I came across the same problem looking for a solution which I didn't find here.

I don't know anything about MVVM so it's probably not MVVM conform but it worked for me.

Step 1: Give your context menu a name.

<Button.ContextMenu>
    <ContextMenu Name="cmTabs"/>
</Button.ContextMenu>

Step 2: Double click the control object and insert this code. Order matters!

Private Sub Button_Click_1(sender As Object, e As Windows.RoutedEventArgs)
        cmTabs.StaysOpen = True
        cmTabs.IsOpen = True
    End Sub

Step 3: Enjoy

This will react for left & right click. It's a button with a ImageBrush with a ControlTemplate.

七婞 2024-10-12 04:40:46

您可以将 contextMenu 的 Isopen 属性绑定到 viewModel 中的属性,例如“IsContextMenuOpen”。
但问题是您无法将上下文菜单直接绑定到 viewModel,因为它不是 userControl 层次结构的一部分。因此,要解决此问题,您应该将 tag 属性绑定到视图的 dataontext。

<Image Tag="{Binding DataContext, ElementName=YourUserControlName}">
<ContextMenu IsOpen="{Binding PlacementTarget.Tag.IsContextMenuOpen,Mode=OneWay}" >
.....
</ContextMenu>
<Image>

祝你好运。

you can bind the Isopen Property of the contextMenu to a property in your viewModel like "IsContextMenuOpen".
but the problem is your can't bind directly the contextmenu to your viewModel because it's not a part of your userControl hiarchy.So to resolve this you should bing the tag property to the dataontext of your view.

<Image Tag="{Binding DataContext, ElementName=YourUserControlName}">
<ContextMenu IsOpen="{Binding PlacementTarget.Tag.IsContextMenuOpen,Mode=OneWay}" >
.....
</ContextMenu>
<Image>

Good luck.

诠释孤独 2024-10-12 04:40:46

XAML

    <Button x:Name="b" Content="button"  Click="b_Click" >
        <Button.ContextMenu >
            <ContextMenu   >
                <MenuItem Header="Open" Command="{Binding OnOpen}" ></MenuItem>
                <MenuItem Header="Close" Command="{Binding OnClose}"></MenuItem>                    
            </ContextMenu>
        </Button.ContextMenu>
    </Button>

C#

    private void be_Click(object sender, RoutedEventArgs e)
        {
        b.ContextMenu.DataContext = b.DataContext;
        b.ContextMenu.IsOpen = true;            
        }

XAML

    <Button x:Name="b" Content="button"  Click="b_Click" >
        <Button.ContextMenu >
            <ContextMenu   >
                <MenuItem Header="Open" Command="{Binding OnOpen}" ></MenuItem>
                <MenuItem Header="Close" Command="{Binding OnClose}"></MenuItem>                    
            </ContextMenu>
        </Button.ContextMenu>
    </Button>

C#

    private void be_Click(object sender, RoutedEventArgs e)
        {
        b.ContextMenu.DataContext = b.DataContext;
        b.ContextMenu.IsOpen = true;            
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文