Свойство ContextMenu IsOpen всегда имеет значение false - PullRequest
0 голосов
/ 25 марта 2019

У меня есть кнопка с 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 при втором щелчке, как никогда не будет установлено.

Я предполагаю, что речь идет о потере фокуса (поправьте меня, если я ошибаюсь) - так как я могу обойти это и оставить его помеченным как открытый, пока не произойдет еще один щелчок?

Ответы [ 3 ]

1 голос
/ 26 марта 2019

Я предполагаю, что речь идет о потере фокуса ...

Да, свойство ContextMenu *1005* не работает, как вы ожидаете.Когда вы нажимаете 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 && 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;
0 голосов
/ 25 марта 2019

Попробуйте это.

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;
        }
    }
}
0 голосов
/ 25 марта 2019

Один из способов достижения желаемого - сохранить значение в свойстве / атрибуте:

public bool IsOpen { get; set; }

private void TestButton_Click(object sender, RoutedEventArgs e)
{
  if (sender is Button button)
  {
     button.ContextMenu.Placement = PlacementMode.Bottom;
     button.ContextMenu.PlacementTarget = button;
     IsOpen = !IsOpen;
     button.ContextMenu.IsOpen = IsOpen;
   }
      Debug.WriteLine(IsOpen);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...