This question relates to the post here - the original question was resolved, but then another cropped up.
As you can see the MenuItem is appearing the wrong side
As the prior issue was related to another control library I tested it with a minimal example...
Opened a new MVC project targeting .NET 8. Gave the grid on the MainWindow a name and then added a ToolBar with a button and a DataGrid. Applied the ContextMenu to each in turn and got the same behavior.
Private Sub MainWindow_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
For i As Integer = 0 To 2
Dim vRow As New RowDefinition
If i = 1 Then
vRow.Height = New GridLength(35, GridUnitType.Star)
Else
vRow.Height = New GridLength(35)
End If
TestGrid.RowDefinitions.Add(vRow)
Next
Dim vToolBar As New ToolBar
With vToolBar
End With
Grid.SetRow(vToolBar, 0)
TestGrid.Children.Add(vToolBar)
Dim vButton As New Button
With vButton
.Content = "Test"
.ContextMenu = ReturnContexMenu()
End With
vToolBar.Items.Add(vButton)
Dim vDG As New DataGrid
With vDG
' .ContextMenu = ReturnContexMenu()
End With
Grid.SetRow(vDG, 1)
TestGrid.Children.Add(vDG)
End Sub
...and this is the ContextMenu
Private Function ReturnContexMenu() As ContextMenu
Try
Dim FlagMI As New MenuItem
With FlagMI
.Header = "Quick Flag"
.Name = "FlagMI"
End With
Dim MarkReadMI As New MenuItem
With MarkReadMI
.Header = "Mark as read"
.Name = "MarkReadMI"
End With
Dim MarkUnreadMI As New MenuItem
With MarkUnreadMI
.Header = "Mark as unread"
.Name = "MarkUnreadMI"
End With
Dim MarkAsMI As New MenuItem
With MarkAsMI
.Header = "Mark as"
.Items.Add(MarkReadMI)
.Items.Add(MarkUnreadMI)
End With
Dim vMainContext As New ContextMenu
With vMainContext
.Name = "MainContextMenu"
.Items.Add(FlagMI)
.Items.Add(MarkAsMI)
End With
Return vMainContext
Catch ex As Exception
Return Nothing
End Try
End Function
I have tried adding a class for MenuItem and adding the DependencyProperty of Primatives.PlacementMode and setting the default value to PlacementMode.Right - in fact I tried every setting, but it has no effect.
Public Class MIx
Inherits System.Windows.Controls.MenuItem
Public Shared ReadOnly HoldingItem As DependencyProperty = DependencyProperty.Register(
name:="IsHoldingItem", propertyType:=GetType(Primitives.PlacementMode), ownerType:=GetType(MIx),
typeMetadata:=New FrameworkPropertyMetadata(defaultValue:=PlacementMode.Right))
Protected Overrides Sub OnInitialized(e As EventArgs)
MyBase.OnInitialized(e)
Style = Nothing
End Sub
Public Property IsHoldingItem As Primitives.PlacementMode
Get
Return GetValue(HoldingItem)
End Get
Set(value As Primitives.PlacementMode)
SetValue(HoldingItem, value)
End Set
End Property
End Class
==========EDIT========
With a big thanks to @BionicCode for all his hard work, it now works
Just in case someone else runs into the same problem onApplyTemplate is...
Public Overrides Sub onApplyTemplate()
MyBase.OnApplyTemplate()
Me.PART_Popup = TryCast(GetTemplateChild("PART_Popup"), Popup)
If Not (Me.PART_Popup) Is Nothing Then
Me.PART_Popup.CustomPopupPlacementCallback = New CustomPopupPlacementCallback(AddressOf OnChildItemHostPlacementChanged)
Me.PART_Popup.Placement = PlacementMode.Custom
End If
End Sub



Your issue is not reproducible. However, I believe it can be fixed for your special scenario when you manually control the placement of the internal
Popupby settingPopup.PlacementtoPlacementMode.Custom:PositionableMenuItem.vb
We extend
MenuItemto gracefully handle the custom positioning of the subitems.The custom
PositionableMenuItemretrieves its internalPopupand sets thePopup.Placementproperty toPlacemmentMode.Custom. This enables thePopupto invoke thePopup.CustomPopupPlacementCallbackthat we define in order to manually align thePopup(the sub-menu items).Use the new
PositionableMenuItem.ChildPlacementproperty to allow the client to select the position (currently only left, top, right and bottom are supported) - see example below.Usage example
You can use
PositionableMenuItemto replace allMenuItemelements or only use it for thoseMenuItemelements that have child items.