Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ElementName Binding from MenuItem in ContextMenu

Has anybody else noticed that Bindings with ElementName do not resolve correctly for MenuItem objects that are contained within ContextMenu objects? Check out this sample:

<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> 

All of the bindings work great except for the bindings contained within the ContextMenu. They print an error to the Output window during runtime.

Any one know of any work arounds? What's going on here?

like image 814
Josh G Avatar asked Jun 18 '09 16:06

Josh G


2 Answers

I found a much simpler solution.

In the code behind for the UserControl:

NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this)); 
like image 92
Josh G Avatar answered Oct 25 '22 14:10

Josh G


As said by others, the 'ContextMenu' is not contained in the visual tree and an 'ElementName' binding won't work. Setting the context menu's 'NameScope' as suggested by the accepted answer only works if the context menu is not defined in a 'DataTemplate'. I have solved this by using the {x:Reference} Markup-Extension which is similar to the 'ElementName' binding but resolves the binding differently, bypassing the visual tree. I consider this to be far more readable than using 'PlacementTarget'. Here is an example:

<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> 

According to the MSDN-documentation

x:Reference is a construct defined in XAML 2009. In WPF, you can use XAML 2009 features, but only for XAML that is not WPF markup-compiled. Markup-compiled XAML and the BAML form of XAML do not currently support the XAML 2009 language keywords and features.

whatever that means... Works for me, though.

like image 21
Marc Avatar answered Oct 25 '22 12:10

Marc