ContextMenu обрезается в некоторых случаях
В настоящее время я делаю контекстное меню, которое открывается щелчком левой кнопки вместо щелчка правой кнопкой мыши, и для этого я блокирую щелчок правой кнопкой мыши, обрабатывая событие 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.
У кого-нибудь есть решение?
3 ответа
Если наконец-то нашли обходной путь, чтобы получить то, что я хочу, даже если это решение должно выделять больше памяти, чем необходимо.
Я воссоздаю все контекстное меню каждый раз, когда контекстное меню должно открываться.
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;
}
Я не уверен, что ты делаешь неправильно. Следующее работает как мне нужно:
<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);
}
}
}
Вы можете смоделировать событие следующим образом:
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);