左键单击 WPF 上下文菜单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4305565/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF Context menu on left click
提问by Relativity
I have a WPF application..In which I have an Image control in Xaml file.
我有一个 WPF 应用程序..其中我在 Xaml 文件中有一个图像控件。
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 ?
我如何以 MVVM 的方式做到这一点?
回答by Ben Wilde
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!
这是仅 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>
回答by Fredrik Hedblad
You can do this by using the MouseDown event of an Image like this
您可以通过使用像这样的图像的 MouseDown 事件来做到这一点
<Image ... MouseDown="Image_MouseDown">
<Image.ContextMenu>
<ContextMenu>
<MenuItem .../>
<MenuItem .../>
</ContextMenu>
</Image.ContextMenu>
</Image>
And then show the ContextMenu in the EventHandler in code behind
然后在后面的代码中显示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;
}
}
回答by slar
You can invent your own DependencyProperty which opens a context menu when image is clicked, just like this:
您可以发明自己的 DependencyProperty,它会在单击图像时打开上下文菜单,如下所示:
<Image Source="..." local:ClickOpensContextMenuBehavior.Enabled="True">
<Image.ContextMenu>...
</Image.ContextMenu>
</Image>
And here is a C# code for that property:
这是该属性的 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;
}
}
}
}
回答by Bruce Wu
you only need add the code into function Image_MouseDown
您只需要将代码添加到函数 Image_MouseDown 中
e.Handled = true;
e.handled = true;
Then it will not disappear.
那么它就不会消失。
回答by Matthis Kohli
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.
我对 MVVM 一无所知,所以它可能不符合 MVVM,但它对我有用。
Step 1: Give your context menu a name.
第 1 步:为您的上下文菜单命名。
<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
第 3 步:享受
This will react for left & right click. It's a button with a ImageBrush with a ControlTemplate.
这将对左键和右键单击做出反应。这是一个带有 ImageBrush 和 ControlTemplate 的按钮。
回答by Flatliner DOA
If you want to do this just in Xaml without using code-behind you can use Expression Blend's triggers support:
如果您只想在 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>
回答by erradi mourad
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.
您可以将 contextMenu 的 Isopen 属性绑定到 viewModel 中的一个属性,例如“IsContextMenuOpen”。但问题是您不能将上下文菜单直接绑定到您的 viewModel,因为它不是您的 userControl hiarchy.So 的一部分。所以要解决这个问题,您应该将标签属性绑定到您的视图的 dataontext。
<Image Tag="{Binding DataContext, ElementName=YourUserControlName}">
<ContextMenu IsOpen="{Binding PlacementTarget.Tag.IsContextMenuOpen,Mode=OneWay}" >
.....
</ContextMenu>
<Image>
Good luck.
祝你好运。
回答by d Koi
XAML
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#
C#
private void be_Click(object sender, RoutedEventArgs e)
{
b.ContextMenu.DataContext = b.DataContext;
b.ContextMenu.IsOpen = true;
}