上下文菜单在某些情况下被剪裁

发布于 2024-12-23 03:31:48 字数 979 浏览 2 评论 0原文

我目前正在制作一个从左键单击而不是右键单击打开的上下文菜单,为此,我通过处理这样的 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。

有人有解决办法吗?

I am currently making a context menu which open from left button click instead of right button click and to do that I inhibit the right click by handling the ContextMenuOpening event like this

private void PinBorder_ContextMenuOpening(object sender, System.Windows.Controls.ContextMenuEventArgs e)
{
    e.Handled = true;
}

and I open the context menu by myself on reaction to the MouseButtonLeftDown event like this :

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

the problem here is when the ContextMenu is opened the first time everything goes well but if I add an item to the observable collection bound to the context menu and try to reopen it, the context menu is clipped to its previous size (if I try to move the context menu selection with up/down key I can guess that an entry has been created but I can't see it because it is clipped).

I tried to remove the click inhibition stuffs and every thing goes well in that case.

I read about such an issue in .net framework 3.5 but i am targeting 4.0.

Does anyone has a solution ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

流心雨 2024-12-30 03:31:48

您可以以这种方式模拟事件:

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

有用的 msdn 参考

You can simulate an event in this fashion:

        ContextMenuAutomationPeer peer = new ContextMenuAutomationPeer(Menu);

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

        invokeProv.Expand();

Using the UIAutomation isn't simple however (and my example doesn't actually work but should point you in the right direction).

You could also try adding something like this to what you already have (before it in your function):

        ContextMenuAutomationPeer peer = new ContextMenuAutomationPeer(Menu);

        peer.RaiseAutomationEvent(AutomationEvents.MenuOpened);

Useful msdn reference.

苦笑流年记忆 2024-12-30 03:31:48

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

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

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

If finally found a workaround to get what I want even if this solution must allocate more memory than necessary.

I recreate the whole contextmenu each time the context menu must open.

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;
}
━╋う一瞬間旳綻放 2024-12-30 03:31:48

我不确定你做错了什么。以下内容符合我的要求:

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

ViewModel:

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

I'm not sure what you're doing wrong. The following works as desired for me:

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

ViewModel:

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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文