从ContextMenu中的MenuItem绑定ElementName

是否有人注意到带有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中包含的绑定之外,所有绑定都很有效。它们在运行时将错误输出到“输出”窗口。


有谁知道任何工作?这里发生了什么?


手掌心
浏览 665回答 3
3回答

慕仙森

我找到了一个更简单的解决方案。在UserControl背后的代码中:NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));

喵喔喔

正如其他人所说,'ContextMenu'不包含在可视树中,'ElementName'绑定不起作用。如果在“DataTemplate”中未定义上下文菜单,则仅按接受的答案建议设置上下文菜单的“NameScope”。我通过使用类似于'ElementName'绑定的{x:Reference}标记扩展来解决这个问题,但绕过可视树以不同方式解析绑定。我认为这比使用'PlacementTarget'更具可读性。这是一个例子:<Image Source="{Binding Image}">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; <Image.ContextMenu>&nbsp; &nbsp; &nbsp; &nbsp; <ContextMenu>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <MenuItem Header="Delete"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Command="{Binding Source={x:Reference Name=Root}, Path=DataContext.RemoveImage}"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CommandParameter="{Binding}" />&nbsp; &nbsp; &nbsp; &nbsp; </ContextMenu>&nbsp; &nbsp; </Image.ContextMenu></Image>根据MSDN文档x:Reference是在XAML 2009中定义的构造。在WPF中,您可以使用XAML 2009功能,但仅适用于非WPF标记编译的XAML。标记编译的XAML和BAML形式的XAML目前不支持XAML 2009语言关键字和功能。无论那意味着什么......但对我而言。

摇曳的蔷薇

这是另一个仅限xaml的解决方法。(这也假设你想要DataContext中的内容,例如,你是MVVM的)选项一,其中ContextMenu的父元素不在DataTemplate中:Command="{Binding PlacementTarget.DataContext.MyCommand,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RelativeSource={RelativeSource AncestorType=ContextMenu}}"这对OP的问题很有用。如果您在DataTemplate中,这将不起作用。在这些情况下,DataContext通常是集合中的众多元素之一,并且您希望绑定的ICommand是同一ViewModel(例如Window 的DataContext)中集合的兄弟属性。在这些情况下,您可以利用Tag暂时保存包含集合和ICommand 的父DataContext:class ViewModel{&nbsp; &nbsp; public ObservableCollection<Derp> Derps { get;set;}&nbsp; &nbsp; public ICommand DeleteDerp {get; set;}}&nbsp;并在xaml<!-- ItemsSource binds to Derps in the DataContext --><StackPanel&nbsp; &nbsp; Tag="{Binding DataContext, ElementName=root}">&nbsp; &nbsp; <StackPanel.ContextMenu>&nbsp; &nbsp; &nbsp; &nbsp; <ContextMenu>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <MenuItem&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Header="Derp"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Command="{Binding PlacementTarget.Tag.DeleteDerp,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RelativeSource={RelativeSource&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AncestorType=ContextMenu}}"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CommandParameter="{Binding PlacementTarget.DataContext,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RelativeSource={RelativeSource AncestorType=ContextMenu}}">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </MenuItem>
打开App,查看更多内容
随时随地看视频慕课网APP