当前位置:  开发笔记 > 编程语言 > 正文

左键单击显示ContextMenu仅使用XAML

如何解决《左键单击显示ContextMenu仅使用XAML》经验,为你挑选了2个好方法。

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

我操纵它,以便我LeftMouseButtonDown在代码隐藏中处理事件,然后显示上下文菜单.

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

这个问题的任何想法或解决方案?



1> Caleb Vear..:

我建议做的是创建一个带有DependencyProperty的新静态类.调用类LeftClickContextMenu和属性Enabled(只是想法).注册DependencyProperty时添加一个更改后的回调.然后在属性更改回调中,如果Enabled设置为true,则向LeftMouseButtonDown事件添加处理程序并在那里执行您的操作.如果Enabled设置为false,则删除处理程序.这可以让你只需在你的xaml中使用以下内容就可以将它设置为任何属性.


此技术称为附加行为,您可以在此代码项目文章中阅读更多相关信息:http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx



2> nightcoder..:

我刚刚根据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()方法中的注释)


优秀的解决方案,为了解决您的评论中引用的绑定问题,您可以设置放置目标:`fe.ContextMenu.PlacementTarget = fe`然后`DataContext ="{Binding Path = PlacementTarget.DataContext,RelativeSource = {RelativeSource Self}}" >`然后,您可以使用ContextMenuService属性(如Placement和Horizo​​ntal/VerticalOffset)来定位它.
推荐阅读
赛亚兔备_393
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有