You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ContextMenu中子MenuItem显示在左侧而非默认位置的问题

嵌套MenuItem显示位置错误问题解决记录

原关联问题已解决,现出现新问题:嵌套的子MenuItem显示在了错误的一侧(本该在右侧,实际出现在左侧)。

问题现象(应用内):嵌套的子菜单显示在父菜单的左侧,而非预期的右侧。

为排除第三方控件库干扰,创建了最小测试示例,复现了相同问题:
最小示例错误效果:右键点击测试按钮后,“Mark as”的子菜单同样错误显示在左侧。

测试环境为目标框架.NET 8的WPF项目,在MainWindow的Grid中添加带Button的ToolBar和DataGrid,为控件设置ContextMenu后出现异常。

窗口初始化代码

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
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
Grid.SetRow(vDG, 1)
TestGrid.Children.Add(vDG)

End Sub 

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

尝试过的无效方案

曾创建自定义MenuItem类,添加Primitives.PlacementMode类型的依赖属性并设置默认值为PlacementMode.Right,尝试所有PlacementMode值均无效:

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

问题解决更新

感谢@BionicCode的帮助,问题已解决:
解决后效果:子菜单正常显示在父菜单的右侧。

以下是修复用的OnApplyTemplate代码,供遇到相同问题的开发者参考:

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

内容的提问来源于stack exchange,提问作者gchq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:44:53