WPF的默认行为ContextMenu
是在用户右键单击时显示它.我希望在ContextMenu
用户左键单击时显示.看起来这应该是一个简单的属性ContextMenu
,但事实并非如此.
我操纵它,以便我LeftMouseButtonDown
在代码隐藏中处理事件,然后显示上下文菜单.
我在我的项目中使用MVVM,这意味着我将DataTemplate
s用于具有上下文菜单的项目.摆脱代码隐藏并找到一种使用XAML中的触发器或属性显示上下文菜单的方法会更加优雅.
这个问题的任何想法或解决方案?
我建议做的是创建一个带有DependencyProperty的新静态类.调用类LeftClickContextMenu和属性Enabled(只是想法).注册DependencyProperty时添加一个更改后的回调.然后在属性更改回调中,如果Enabled设置为true,则向LeftMouseButtonDown事件添加处理程序并在那里执行您的操作.如果Enabled设置为false,则删除处理程序.这可以让你只需在你的xaml中使用以下内容就可以将它设置为任何属性.
此技术称为附加行为,您可以在此代码项目文章中阅读更多相关信息:http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx
我刚刚根据HK1的答案编写并测试了这个(您还可以阅读附加属性概述中的附加属性):
public static class ContextMenuLeftClickBehavior { public static bool GetIsLeftClickEnabled(DependencyObject obj) { return (bool)obj.GetValue(IsLeftClickEnabledProperty); } public static void SetIsLeftClickEnabled(DependencyObject obj, bool value) { obj.SetValue(IsLeftClickEnabledProperty, value); } public static readonly DependencyProperty IsLeftClickEnabledProperty = DependencyProperty.RegisterAttached( "IsLeftClickEnabled", typeof(bool), typeof(ContextMenuLeftClickBehavior), new UIPropertyMetadata(false, OnIsLeftClickEnabledChanged)); private static void OnIsLeftClickEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) { var uiElement = sender as UIElement; if(uiElement != null) { bool IsEnabled = e.NewValue is bool && (bool) e.NewValue; if(IsEnabled) { if(uiElement is ButtonBase) ((ButtonBase)uiElement).Click += OnMouseLeftButtonUp; else uiElement.MouseLeftButtonUp += OnMouseLeftButtonUp; } else { if(uiElement is ButtonBase) ((ButtonBase)uiElement).Click -= OnMouseLeftButtonUp; else uiElement.MouseLeftButtonUp -= OnMouseLeftButtonUp; } } } private static void OnMouseLeftButtonUp(object sender, RoutedEventArgs e) { Debug.Print("OnMouseLeftButtonUp"); var fe = sender as FrameworkElement; if(fe != null) { // if we use binding in our context menu, then it's DataContext won't be set when we show the menu on left click // (it seems setting DataContext for ContextMenu is hardcoded in WPF when user right clicks on a control, although I'm not sure) // so we have to set up ContextMenu.DataContext manually here if (fe.ContextMenu.DataContext == null) { fe.ContextMenu.SetBinding(FrameworkElement.DataContextProperty, new Binding { Source = fe.DataContext }); } fe.ContextMenu.IsOpen = true; } } }
...
(注意OnMouseLeftButtonUp()方法中的注释)