【问题标题】:ContextMenu clipped in some caseContextMenu 在某些情况下被剪裁
【发布时间】: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() 但没有任何改变。
  • 这有点骇人听闻......但也许你可以通过模拟右键单击打开它?
  • 你知道怎么做吗?

标签: wpf contextmenu clipping


【解决方案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;
}

【讨论】:

【解决方案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 TestCommand{get;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/… 一个有趣的事情是我试图像你一样在另一个项目中复制这个错误和一切工作。它并没有真正帮助,因为我不知道是什么阻止了上下文菜单扩展是我以前的情况,但它确实是。
  • 我认为这是您的应用程序特有的问题。我进行了一些搜索,发现了您遇到的问题,但我认为它们与您遇到的问题不同;它们都涉及裁剪上下文菜单的一侧,而不是不显示最新的项目。我的建议是逐步删除程序的某些部分,直到它开始工作,然后您就会知道哪个部分导致了问题。
猜你喜欢
  • 2012-01-14
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 2014-07-25
  • 1970-01-01
  • 2011-03-20
相关资源
最近更新 更多