.net - 仅使用 XAML 在左键单击时显示上下文菜单

标签 .net wpf xaml mvvm contextmenu

WPF ContextMenu 的默认行为是在用户右键单击时显示它。我希望当用户单击鼠标左键时显示 ContextMenu。看起来这应该是 ContextMenu 上的一个简单属性,但事实并非如此。

我对其进行了操纵,以便在代码隐藏中处理 LeftMouseButtonDown 事件,然后显示上下文菜单。

我在项目中使用 MVVM,这意味着我对具有上下文菜单的项目使用 DataTemplate。摆脱代码隐藏并找到一种使用 XAML 中的触发器或属性来显示上下文菜单的方法会更加优雅。

对于这个问题有什么想法或解决方案吗?

最佳答案

我刚刚根据 HK1 的答案编写并测试了这个(您还可以在 Attached Properties Overview) 中阅读有关附加属性的信息:

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

}

...

<Button Content="Do All" local:ContextMenuLeftClickBehavior.IsLeftClickEnabled="True" >
    <Button.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Make everything awesome" />
            <MenuItem Header="Control the World" />
        </ContextMenu>
    </Button.ContextMenu>
</Button>

(请注意 OnMouseLeftButtonUp() 方法内的注释)

关于.net - 仅使用 XAML 在左键单击时显示上下文菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/555252/

相关文章:

c# - 强制 ErrorText 显示在 DataGridView 中

.net - 多文档应用程序的 MVVM 设计?

wpf - 在WPF内容中看不到_(下划线)

xaml - 加载 ViewModel 时绑定(bind) Picker 和 DatePicker 的默认值

c# - SL 5 脱离浏览器,提升信任度 - 从任何本地目录显示 PNG

c# - Array.Copy 总是行优先?

c# - Module 是 Autofac 的绑定(bind)上下文吗

.net - 使用任务并行库发送邮件会引发错误

c# - 鼠标单击 Canvas 中的对象

c# - “文本”属性不能从属性触发器设置并同时出现在触发器的条件中