为了账号安全,请及时绑定邮箱和手机立即绑定

从ContextMenu中的MenuItem绑定ElementName

从ContextMenu中的MenuItem绑定ElementName

手掌心 2019-09-02 15:08:44
是否有人注意到带有ElementName的Bindings无法正确解析MenuItem对象中包含的ContextMenu对象?看看这个样本:<Window x:Class="EmptyWPF.Window1"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    Title="Window1" Height="300" Width="300"    x:Name="window">    <Grid x:Name="grid" Background="Wheat">        <Grid.ContextMenu>            <ContextMenu x:Name="menu">                <MenuItem x:Name="menuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>                <MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>                <MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>                <MenuItem Header="Menu Item" Tag="{Binding ElementName=menuItem}" Click="MenuItem_Click"/>            </ContextMenu>        </Grid.ContextMenu>        <Button Content="Menu"                 HorizontalAlignment="Center" VerticalAlignment="Center"                 Click="MenuItem_Click" Tag="{Binding ElementName=menu}"/>        <Menu HorizontalAlignment="Center" VerticalAlignment="Bottom">            <MenuItem x:Name="anotherMenuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>            <MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>            <MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>            <MenuItem Header="Menu Item" Tag="{Binding ElementName=anotherMenuItem}" Click="MenuItem_Click"/>        </Menu>    </Grid></Window>除了ContextMenu中包含的绑定之外,所有绑定都很有效。它们在运行时将错误输出到“输出”窗口。有谁知道任何工作?这里发生了什么?
查看完整描述

3 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

我找到了一个更简单的解决方案。


在UserControl背后的代码中:


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


查看完整回答
反对 回复 2019-09-02
?
喵喔喔

TA贡献1735条经验 获得超5个赞

正如其他人所说,'ContextMenu'不包含在可视树中,'ElementName'绑定不起作用。如果在“DataTemplate”中未定义上下文菜单,则仅按接受的答案建议设置上下文菜单的“NameScope”。我通过使用类似于'ElementName'绑定的{x:Reference}标记扩展来解决这个问题,但绕过可视树以不同方式解析绑定。我认为这比使用'PlacementTarget'更具可读性。这是一个例子:


<Image Source="{Binding Image}">       

    <Image.ContextMenu>

        <ContextMenu>

            <MenuItem Header="Delete" 

                      Command="{Binding Source={x:Reference Name=Root}, Path=DataContext.RemoveImage}"

                      CommandParameter="{Binding}" />

        </ContextMenu>

    </Image.ContextMenu>

</Image>

根据MSDN文档


x:Reference是在XAML 2009中定义的构造。在WPF中,您可以使用XAML 2009功能,但仅适用于非WPF标记编译的XAML。标记编译的XAML和BAML形式的XAML目前不支持XAML 2009语言关键字和功能。


无论那意味着什么......但对我而言。


查看完整回答
反对 回复 2019-09-02
?
摇曳的蔷薇

TA贡献1793条经验 获得超6个赞

这是另一个仅限xaml的解决方法。(这也假设你想要DataContext中的内容,例如,你是MVVM的)


选项一,其中ContextMenu的父元素不在DataTemplate中:


Command="{Binding PlacementTarget.DataContext.MyCommand, 

         RelativeSource={RelativeSource AncestorType=ContextMenu}}"

这对OP的问题很有用。如果您在DataTemplate中,这将不起作用。在这些情况下,DataContext通常是集合中的众多元素之一,并且您希望绑定的ICommand是同一ViewModel(例如Window 的DataContext)中集合的兄弟属性。


在这些情况下,您可以利用Tag暂时保存包含集合和ICommand 的父DataContext:


class ViewModel

{

    public ObservableCollection<Derp> Derps { get;set;}

    public ICommand DeleteDerp {get; set;}

并在xaml


<!-- ItemsSource binds to Derps in the DataContext -->

<StackPanel

    Tag="{Binding DataContext, ElementName=root}">

    <StackPanel.ContextMenu>

        <ContextMenu>

            <MenuItem

                Header="Derp"                       

                Command="{Binding PlacementTarget.Tag.DeleteDerp, 

                RelativeSource={RelativeSource 

                                    AncestorType=ContextMenu}}"

                CommandParameter="{Binding PlacementTarget.DataContext, 

                RelativeSource={RelativeSource AncestorType=ContextMenu}}">

            </MenuItem>


查看完整回答
反对 回复 2019-09-02
  • 3 回答
  • 0 关注
  • 664 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信