ContextMenu的奇怪行为:放置";镜像”;

本文关键字:quot 镜像 放置 ContextMenu | 更新日期: 2024-07-27 20:09:33

在使用ContextMenu时,我遇到了一个非常奇怪的行为(至少对我来说)。以下是简化的xaml(MainWindow.xml):

<Window x:Class="ContextMenuTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="500"
        Height="300">
  <Button Content="Do this" Height="25" Width="80" ContextMenuService.Placement="Right">
    <Button.ContextMenu>
      <ContextMenu>
        <MenuItem Header="Do this" />
        <MenuItem Header="Do that" />
      </ContextMenu>
    </Button.ContextMenu>
  </Button>
</Window>

使用此xaml,右键单击按钮的预期结果是位于按钮右侧的ContextMenu。但结果是:

https://i.stack.imgur.com/pSd0Q.png

因此,ContextMenu奇怪地位于按钮的左侧。我还尝试将属性ContextMenuService.Placement设置为LeftTopBottom。结果是:

  • Left->ContextMenu位于按钮的右侧
  • Top->ContextMenu位于按钮的右上方。(非顶部-左侧
  • Bottom->ContextMenu位于按钮的底部-右侧(而不是底部-左侧

在我看来,坐标系是镜像的(也就是说,坐标系的原点在窗口的右上角,而不是左上角)。我不知道为什么。我需要帮助将ContextMenu放置在按钮的左下角。

(附言:此示例项目与Visual Studio 2013创建的默认项目相同,除了MainWindow.xaml。)

ContextMenu的奇怪行为:放置";镜像”;

好的,我终于找到了解决方案(是的,终于)。这个问题可能与这里描述的问题同构:带有弹出的WPF Handedness

所以我写了一个行为:

namespace Test {
  public class WorkaroundForTheBugOfPopupBehavior : Behavior<FrameworkElement> {
    private static readonly FieldInfo _menuDropAlignmentField;
    static WorkaroundForTheBugOfContextMenuBehavior() {
      _menuDropAlignmentField = typeof(SystemParameters).GetField("_menuDropAlignment", BindingFlags.NonPublic | BindingFlags.Static);
      System.Diagnostics.Debug.Assert(_menuDropAlignmentField != null);
      EnsureStandardPopupAlignment();
      SystemParameters.StaticPropertyChanged += OnStaticPropertyChanged;
    }
    private static void EnsureStandardPopupAlignment() {
      if (SystemParameters.MenuDropAlignment && _menuDropAlignmentField != null) {
        _menuDropAlignmentField.SetValue(null, false);
      }
    }
    private static void OnStaticPropertyChanged(object sender, PropertyChangedEventArgs e) {
      EnsureStandardPopupAlignment();
    }
  }
}

并将其连接到主窗口:

  <i:Interaction.Behaviors>
    <local:WorkaroundForTheBugOfPopupBehavior />
  </i:Interaction.Behaviors>

其中:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
xmlns:local="clr-namespace:Test"

问题已经过去了。希望这能帮助其他人。。。