Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF ContextMenu placement adjusted event

Does anyone know of how I can determine when the ContextMenu get its placement automatically adjusted due to being too close to the edge of the screen?

My scenario is that I have a ContextMenu that has 2 rounded corners and 2 square corners. When the menu opens down I round the bottom 2, and if the menu is opening upwards then I round the top 2. The problem is that I haven't found an event or property to bind to that tells me when the menu gets its direction automatically changed.

Here's some simplified sample code to try out. If you click when the window is at top of screen then menu goes down. If you move window to bottom of screen then the menu will go up.

<Window x:Class="menuRedirection.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="100" Width="200">
  <DockPanel Name="panel" ContextMenuOpening="DockPanel_ContextMenuOpening">
    <DockPanel.ContextMenu>
      <ContextMenu>
        <MenuItem Header="item"/>
        <MenuItem Header="item"/>
        <MenuItem Header="item"/>
        <MenuItem Header="item"/>
      </ContextMenu>
    </DockPanel.ContextMenu>
    <Rectangle DockPanel.Dock="Bottom" Name="menuTarget" Fill="Red" Height="10"/>
    <TextBlock DockPanel.Dock="Top" Text="right click for context menu"/>
  </DockPanel>
</Window>

private void DockPanel_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
  ContextMenuService.SetPlacement(panel, PlacementMode.Bottom);
  ContextMenuService.SetPlacementTarget(panel, menuTarget);
}

Here's what the real application looks like so you can see my problem with needing to know to adjust my rounded corners.

enter image description here

like image 719
Bill Tarbell Avatar asked Mar 10 '26 02:03

Bill Tarbell


1 Answers

As far as I can tell, this is not possible.

Using JustDecompile, I traced this functionality to the UpdatePosition method in the Popup class. The final location seems to be set here:

    this._positionInfo.X = num4;
    this._positionInfo.Y = num5;
    this._secHelper.SetPopupPos(true, num4, num5, false, 0, 0);

_secHelper is a helper class of type PopupSecurityHelper, and seems to just be an internal helper...And, none of these result in an event or even a public property being changed.

Here is an MSDN article explaining how popup positioning is determined in general (The 'When the popup encounters the edge of a screen' describes your scenario).

However, this article explains how you can use the CustomPopupPlacementCallback to override these behaviors somewhat. However, this still uses a PopupPrimaryAxis, which should flip the menu as necessary, and will result in the same problem.

The only other thing I could think of is that you could look into the PlacementRectangle and maybe poll the size and location similar to how UpdatePosition does things...or just check the popup itself just like UpdatePosition does.

This is a private method, though. So, any logic you try to mimic could change in a future version of the framework.

UPDATE

Also, you could possibly try bastardizing PointToScreen or PointFromScreen, but that would be very convoluted code if it worked...

like image 129
Justin Pihony Avatar answered Mar 13 '26 16:03

Justin Pihony



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!