ContextMenu 在某些情况下被剪裁

Posted

技术标签:

【中文标题】ContextMenu 在某些情况下被剪裁【英文标题】:ContextMenu clipped in some case 【发布时间】:2012-01-28 09:34:09 【问题描述】:

我目前正在制作一个上下文菜单,它从左键单击而不是右键单击打开,为此我通过像这样处理 ContextMenuOpening 事件来禁止右键单击

private void PinBorder_ContextMenuOpening(object sender, System.Windows.Controls.ContextMenuEventArgs e)

    e.Handled = true;

我自己打开上下文菜单,以响应 MouseButtonLeftDown 事件,如下所示:

private void PinBorder_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)

    PinBorder.ContextMenu.PlacementTarget = PinBorder;
    PinBorder.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Center;
    PinBorder.ContextMenu.HorizontalOffset = 0;
    PinBorder.ContextMenu.VerticalOffset = 0;
    PinBorder.ContextMenu.IsOpen = true;
    e.Handled = true;

这里的问题是,当第一次打开 ContextMenu 时一切正常,但是如果我将一个项目添加到绑定到上下文菜单的可观察集合并尝试重新打开它,上下文菜单会被剪裁到之前的大小(如果我尝试使用向上/向下键移动上下文菜单选择 我可以猜到已经创建了一个条目,但我看不到它,因为它被剪辑了)。

我试图删除点击抑制的东西,在这种情况下一切都很顺利。

我在 .net framework 3.5 中读到过这样的问题,但我的目标是 4.0。

有人有解决办法吗?

【问题讨论】:

我现在不在可以测试它的计算机上,但我的第一个想法是上下文菜单控件设置为在右键单击时调整大小,并且以这种方式打开它不会t 触发调整大小功能。也许尝试在您的上下文菜单上调用UpdateLayout() 我尝试了 UpdateLayout() 和 InvalidateMeasure() 但没有任何改变。 这有点骇人听闻......但也许你可以通过模拟右键单击打开它? 你知道怎么做吗? 【参考方案1】:

你可以用这种方式模拟一个事件:

        ContextMenuAutomationPeer peer = new ContextMenuAutomationPeer(Menu);

        IExpandCollapseProvider invokeProv = peer.GetPattern(PatternInterface.ExpandCollapse) as IExpandCollapseProvider;

        invokeProv.Expand();

然而,使用 UIAutomation 并不简单(我的示例实际上并不能正常工作,但应该为您指明正确的方向)。

你也可以尝试在你已经拥有的东西上添加这样的东西(在你的函数中):

        ContextMenuAutomationPeer peer = new ContextMenuAutomationPeer(Menu);

        peer.RaiseAutomationEvent(AutomationEvents.MenuOpened);

Useful msdn reference.

【讨论】:

我尝试了第一段代码,但它不起作用(如你所说),因为我无法让模式返回 null。第二段代码有效,但没有解决问题。谢谢你的尝试。 ;)【参考方案2】:

如果最终找到了一种解决方法来获得我想要的东西,即使这个解决方案必须分配比必要更多的内存。

每次必须打开上下文菜单时,我都会重新创建整个上下文菜单。

private void PinBorder_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)

    PropertyInputPin.UpdateCompatibleAdjusters();

    PinBorder.ContextMenu = new System.Windows.Controls.ContextMenu();

    Binding binding = new Binding("CompatibleAdjusters");
    binding.Mode = BindingMode.OneWay;
    binding.Source = DataContext;
    BindingOperations.SetBinding(PinBorder.ContextMenu, ContextMenu.ItemsSourceProperty, binding);

    PinBorder.ContextMenu.PlacementTarget = PinBorder;
    PinBorder.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Center;
    PinBorder.ContextMenu.HorizontalOffset = 0;
    PinBorder.ContextMenu.VerticalOffset = 0;
    PinBorder.ContextMenu.IsOpen = true;

    for (int i = 0; i < PropertyInputPin.CompatibleAdjusters.Count; i++)
    
        MenuItem mi = PinBorder.ContextMenu.ItemContainerGenerator.ContainerFromIndex(i) as MenuItem;
        mi.Click += ContextMenu_Click;
    

    e.Handled = false;

【讨论】:

问题仍然存在,需要更好的解决方案。 我认为这个是更好的解决方案:***.com/questions/8642910/…【参考方案3】:

我不确定你做错了什么。以下对我来说是可行的:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525" x:Name="mainWindow">
    <Window.DataContext>
        <local:Class1></local:Class1>
    </Window.DataContext>
    <Grid x:Name="grid" Background="Blue" MouseLeftButtonDown="Grid_MouseLeftButtonDown" ContextMenuOpening="grid_ContextMenuOpening">
        <Grid.RowDefinitions>
            <RowDefinition Height="200"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ContextMenu>
            <ContextMenu x:Name="contextMenu" ItemsSource="Binding menuItems">
            </ContextMenu>
        </Grid.ContextMenu>
        <Button Height="100" Command="Binding TestCommand" Grid.Row="1"></Button>
    </Grid>
</Window>


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication2

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    

        private List<MenuItem> list;

        public List<MenuItem> menuItems
        
            get  return list; 
            set  list = value; 
        

        public MainWindow()
        
            InitializeComponent();

            list = new List<MenuItem>();
            MenuItem item = new MenuItem();
            item.Header = "One";
            list.Add(item);
            item = new MenuItem();
            item.Header = "Two";
            list.Add(item);
            item = new MenuItem();
            item.Header = "Three";
            list.Add(item);
        

        private void Button_Click(object sender, RoutedEventArgs e)
        
            MenuItem item = new MenuItem();
            item.Header = "Four";
            menuItems.Add(item);
            contextMenu.Items.Add(item);
        

        private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        
            grid.ContextMenu.PlacementTarget = grid;
            grid.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Center;
            grid.ContextMenu.HorizontalOffset = 0;
            grid.ContextMenu.VerticalOffset = 0;
            grid.ContextMenu.IsOpen = true;
            e.Handled = true;
        

        private void grid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        
            e.Handled = true;
        
    

视图模型:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;

namespace WpfApplication2

    public class Class1
    

        private List<MenuItem> list;

        public List<MenuItem> menuItems
        
            get  return list; 
            set  list = value; 
        

        public string test
        
            get;
            set;
        

        public Class1()
        
            test = "1";

            list = new List<MenuItem>();
            MenuItem item = new MenuItem();
            item.Header = "One";
            list.Add(item);
            item = new MenuItem();
            item.Header = "Two";
            list.Add(item);
            item = new MenuItem();
            item.Header = "Three";
            list.Add(item);
            TestCommand = new DelegateCommand(Button_Click);
        

        public ICommand TestCommandget;private set;

        private void Button_Click()
        
            MenuItem item = new MenuItem();
            item.Header = "Four";
            menuItems.Add(item);
        
    

【讨论】:

我在 Windows 7 上。你有其他人讨论这个问题的链接吗? 我也尝试过微软论坛:social.msdn.microsoft.com/Forums/en-US/wpf/thread/… 我还发现了这个:social.msdn.microsoft.com/Forums/en-NZ/wpf/thread/… 和这个:social.msdn.microsoft.com/Forums/en-US/wpf/thread/… 一个有趣的事情是我试图像你一样在另一个项目中复制这个错误和一切工作。它并没有真正帮助,因为我不知道是什么阻止了上下文菜单扩展是我以前的情况,但它确实是。 我认为这是您的应用程序特有的问题。我进行了一些搜索,发现了您遇到的问题,但我认为它们与您遇到的问题不同;它们都涉及裁剪上下文菜单的一侧,而不是不显示最新的项目。我的建议是逐步删除程序的某些部分,直到它开始工作,然后您就会知道哪个部分导致了问题。

以上是关于ContextMenu 在某些情况下被剪裁的主要内容,如果未能解决你的问题,请参考以下文章

C#:按钮图像在底部被剪裁

将 .csv 导入 MySQL 数据库时,某些数据在没有明显原因的情况下被修改,知道吗?

Fragment 中 ListView绑定ContextMenu

是否可以在 VS2015 Live Visual Tree 中查看 ContextMenu 的实时属性?

为啥启用透明度会导致剪裁问题?

需要帮助以比剪裁优惠更复杂的方式通过某些文本显示背景