【问题标题】:How to access a control from a ContextMenu menuitem via the visual tree?如何通过可视化树从 ContextMenu menuitem 访问控件?
【发布时间】:2012-07-05 04:34:11
【问题描述】:

这似乎是一个很受欢迎的话题,但是...

我有以下 XAML:

<internal:MyCommandObject x:Name="CommandModel"/>

<Button DockPanel.Dock="Bottom" Command="{Binding DoAction, ElementName=CommandModel}">
    <Button.ContextMenu>
        <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
            <MenuItem Command="{Binding DoAction, ElementName=CommandModel}"/>
        </ContextMenu>
    </Button.ContextMenu>
    Click Me
</Button>

现在,MyCommandObject 是一个控件,它公开来自其DataContext 的动态命令。你知道接下来会发生什么。 :)

基本上,按钮命令完美运行 - 当我单击它时,MyCommandObject 上的 DoAction 命令完美执行。但是,菜单项中的命令不会被执行。我尝试了各种技巧,例如将上下文菜单datacontext 设置为placementTarget,以便它可以遍历控件的可视化树等等,但什么也没做。

我需要RelativeSourceCommandTarget 符文的什么特定对齐才能使其工作?

【问题讨论】:

    标签: wpf xaml binding contextmenu relativesource


    【解决方案1】:

    发生这种情况是因为DataContext="{Binding PlacementTarget,... 绑定会将按钮设置为MenuItems DataContext,但这不会将ContextMenu 添加到窗口的VisualTree 中,这就是ElementName 绑定不起作用的原因。使用ElementName 绑定的一个简单解决方法是将其添加到 Window/UserControl 的代码隐藏中:

    NameScope.SetNameScope(contextMenuName, NameScope.GetNameScope(this)); 
    

    另一种解决方案是这样做 -

    <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">   
        <MenuItem Command="{Binding DataContext.DoAction}"/>   
    </ContextMenu>
    

    DataContext="{Binding PlacementTarget,... 会将 Button(Placementtarget) 设置为您的 ContextMenu 的 DataContext,因此您可以使用 Button 的 DataContext 来绑定命令。

    更新:

    您可以尝试使用NameScope.NameScope Attached Property 在 XAML 中设置 NameScope,但我不确定您将如何在没有代码的情况下获得父窗口的 NameScope!

    您必须执行类似于以下 Josh Smith 的文章的操作,他提供了一种在 XAML 中执行此操作的方法;但这也涉及代码(不仅仅是那一行代码)-

    Enable ElementName Bindings with ElementSpy

    有什么不使用这行代码的具体原因吗?

    【讨论】:

    • 谢谢。如果可能,我试图不使用代码隐藏 - 是否可以在 XAML 中定义 NameScope?不幸的是,我无法将菜单项的数据上下文设置为公开命令的按钮。这是网格的上下文菜单,我需要所选项目的 DataContext,以便我可以将其中的属性作为参数传递给命令。
    • 不使用代码背后的原因是 xaml 没有被编译 - 一切都是在运行时使用后期绑定在客户端完成的。
    • @Webreaper 不确定您是在谈论您的场景还是在一般情况下,但大多数 XAML 文件在构建时被编译成 BAML(查看您的 xaml 也是如此);我建议您参考这些链接 - Compiled XAML = BAML not ILB is for... BAML
    • 有道理;我没有使用 Loose XAML,但根据 this 发布 A loose XAML file can't include the x:Class XAML keyword;所以,如果这是正确的,那么你将无法实现你想要的!
    • 很奇怪。我不认为那是我!
    猜你喜欢
    • 1970-01-01
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 2018-04-28
    相关资源
    最近更新 更多