首页 > 解决方案 > ContextMenu IsOpen 属性始终为 false

问题描述

我有一个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属性 - 如果当前值为 true,则将其设置为 false,反之亦然。

我的问题是,即使在第一次单击时将IsOpen属性值设置为从falsetrue,但它始终保留false在第二次单击时,就像它永远不会被设置一样。

我认为这是关于失去焦点(纠正我,如果我错了) - 那么我该如何解决这个问题并将其标记为打开,直到发生另一次点击?

标签: c#wpfcontextmenu

解决方案


我认为这是关于失去焦点...

是的,ContextMenu'StaysOpen属性没有按您预期的那样工作。当您单击 时ButtonContextMenu确实已关闭。

您可以通过使用DependencyPropertyDescriptor跟踪ContextMenu关闭时间的 a 来解决此问题,然后将经过的时间与事件处理程序中的某个常量值进行比较。这应该有效:

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;

推荐阅读