1

I've got faced a really strange behavior (at least for me) while using ContextMenu. Here's simplified xaml (MainWindow.xaml):

<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>

With this xaml, the expected result by right-clicking the button is a ContextMenu placed at the right of the button. But the result is:

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

So, the ContextMenu is strangely placed at the left of the button. I also tried to set the property ContextMenuService.Placement to Left, Top, Bottom. And the result is:

  • Left -> The ContextMenu is placed at the right of the button.
  • Top -> The ContextMenu is placed at the top-right of the button. (not top-left)
  • Bottom -> The ContextMenu is placed at the bottom-right of the button (not bottom-left)

It seems to me that the coordinate system is mirrored (that is, the origin of the coordinate system is at the top-right of the window, not top-left). I don't know why at all. I need help to place the ContextMenu at the bottom-left of the button.

(P.S. This sample project is the same as the default project created by Visual Studio 2013 except the MainWindow.xaml.)

kitalt
  • 11
  • 2

1 Answers1

0

OK, I finally (yes, finally) found the solution. The problem is maybe isomorphic to the one described here: WPF Handedness with Popups

So I wrote a behavior:

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();
    }
  }
}

... and attached it to MainWindow:

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

where:

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

And the problem is gone. Hope this helps someone else...

Community
  • 1
  • 1
kitalt
  • 11
  • 2