#c# #wpf #contextmenu
#c# #wpf #contextmenu
Вопрос:
У меня есть кнопка с ContextMenu
установленным следующим образом:
<Button
x:Name="TestButton"
Click="TestButton_Click">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="Sample Menu Item 1" />
<MenuItem Header="Sample Menu Item 2" />
<MenuItem Header="Sample Menu Item 3" />
</ContextMenu>
</Button.ContextMenu>
</Button>
Код, лежащий в основе:
private void TestButton_Click(object sender, RoutedEventArgs e)
{
// This always prints false, even though the contextmenu is currently opened
System.Console.WriteLine(button.ContextMenu.IsOpen);
if (sender is Button button)
{
button.ContextMenu.Placement = PlacementMode.Bottom;
button.ContextMenu.PlacementTarget = button;
button.ContextMenu.StaysOpen = true;
button.ContextMenu.IsOpen = !button.ContextMenu.IsOpen; // Doesn't work!
}
}
Итак, я настроил ContextMenu
на открытие одним щелчком мыши, и это работает, однако я хотел бы переключать ContextMenu
видимость при каждом нажатии кнопки. Для этого я хочу использовать IsOpen
свойство — присвоить ему значение false, если текущее значение равно true, и наоборот.
Моя проблема в том, что, хотя IsOpen
значение свойства устанавливается от false
до true
при первом нажатии, оно всегда остается false
при втором нажатии, как будто оно никогда не будет установлено.
Я предполагаю, что это связано с потерей фокуса (поправьте меня, если я ошибаюсь) — итак, как я могу обойти это и сохранить его помеченным как открытый, пока не произойдет другой щелчок?
Комментарии:
1. @NawedNabiZada Что касается присвоения имени ContextMenu — это так не сработает, результаты те же, что и в текущем коде. Я безуспешно пытался заставить его работать в чистом XAML, следовательно, код позади.
2. Потому что ContextMenu фактически закрывается перед вводом события
Ответ №1:
Я предполагаю, что речь идет о потере фокуса…
Да, свойство ContextMenu
‘s StaysOpen
работает не так, как вы ожидаете. Когда вы нажимаете на Button
, ContextMenu
оно действительно закрывается.
Вы могли бы обойти это, используя DependencyPropertyDescriptor
который отслеживает, когда ContextMenu
было закрыто, а затем сравнивает прошедшее время с некоторым постоянным значением в вашем обработчике событий. Это должно сработать:
private DependencyPropertyDescriptor _dpd;
private DateTime _closeTime;
private void TestButton_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button)
{
button.ContextMenu.Placement = PlacementMode.Bottom;
button.ContextMenu.PlacementTarget = button;
button.ContextMenu.IsOpen = !button.ContextMenu.IsOpen amp;amp; DateTime.UtcNow.Subtract(_closeTime).TotalMilliseconds > 250;
if (_dpd == null)
{
_dpd = DependencyPropertyDescriptor.FromProperty(ContextMenu.IsOpenProperty, typeof(ContextMenu));
_dpd.AddValueChanged(button.ContextMenu, OnContextMenuClosed);
}
}
}
private void OnContextMenuClosed(object sender, EventArgs e) => _closeTime = DateTime.UtcNow;
Ответ №2:
Попробуйте это.
private bool _isOpen = false;
private void TestButton_Click(object sender, RoutedEventArgs e)
{
// This always prints false, even though the contextmenu is currently opened
//System.Console.WriteLine(button.ContextMenu.IsOpen);
if (sender is Button button)
{
if (_isOpen)
{
button.ContextMenu.IsOpen = false;
_isOpen = false;
}
else
{
button.ContextMenu.Placement = PlacementMode.Bottom;
button.ContextMenu.PlacementTarget = button;
button.ContextMenu.StaysOpen = true;
_isOpen = true;
button.ContextMenu.IsOpen = _isOpen;
}
}
}