WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference
I have the following XAML:
<UserControl x:Class="EMS.Controls.Dictionary.TOCControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:EMS.Controls.Dictionary.Models"
xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"
x:Name="root" >
<TreeView
x:Name="TOCTreeView"
Background="White"
Padding="3,5"
ContextMenuOpening="TOCTreeView_ContextMenuOpening"
ItemsSource="{Binding Children}" BorderBrush="{x:Null}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children, Mode=OneTime}">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<!--<ColumnDefinition Width="Auto"/>-->
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--<CheckBox VerticalAlignment="Center" IsChecked="{Binding IsVisible}"/>-->
<ContentPresenter Grid.Column="0" Height="16" Width="20"
Content="{Binding LayerRepresentation}" />
<!--<ContentPresenter Grid.Column="1" >
<ContentPresenter.Content>
Test
</ContentPresenter.Content>
</ContentPresenter>-->
<TextBlock Grid.Column="2" FontWeight="Normal" Text="{Binding Path=Alias, Mode=OneWay}" >
<ToolTipService.ToolTip>
<TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
</ToolTipService.ToolTip>
</TextBlock>
</Grid>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Children, Mode=OneTime}">
<!--<DataTemplate>-->
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox VerticalAlignment="Center" IsChecked="{Binding IsVisible}"/>
开发者_C百科 <ContentPresenter Grid.Column="1"
Content="{Binding LayerRepresentation, Mode=OneWay}" />
<TextBlock Margin="0,1,0,1" Text="{Binding Path=Alias, Mode=OneWay}" Grid.Column="2">
<ToolTipService.ToolTip>
<TextBlock Text="{Binding Description}" TextWrapping="Wrap"/>
</ToolTipService.ToolTip>
</TextBlock>
</Grid>
<!--</DataTemplate>-->
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ContextMenu>
<ContextMenu>
<MenuItem Name="miRemove" Header="Remove"
Command="{Binding ElementName=root, Path=RemoveItemCmd,
diagnostics:PresentationTraceSources.TraceLevel=High}">
<MenuItem.Icon>
<Image Source="../images/16x16/Delete.png"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Properties"
Command="{Binding ElementName=root, Path=GetItemPropertiesCmd}"/>
</ContextMenu>
</TreeView.ContextMenu>
</TreeView>
</UserControl>
Code behind for this UserControl has two ICommand properties with names: RemoveItemCmd and GetItemPropertiesCmd. However, I get
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=root'. BindingExpression:Path=RemoveItemCmd; DataItem=null; target element is 'MenuItem' (Name='miRemove'); target property is 'Command' (type 'ICommand') System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=root'. BindingExpression:Path=GetItemPropertiesCmd; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')
when UserControl is constructed. Why is this and how do I resolve?
You can't bind using element name from a context menu. The link is broken between the context menu and its placement target. You can get around it using a couple of tricks though...
- Use RoutedUICommands with a command binding on the UserControl, then no binding is needed.
Use the placement target binding on the context menu's DataContext. This allows you to at least get the data context of the element the context menu appears on to the context menu.
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=PlacementTarget.DataContext}"
(and i think this is what you want) You can access a static resource, ElementSpy lets you link to the window using a static resource so you can then use a defacto ElementName bindings.
Best solution here ElementName Binding from MenuItem in ContextMenu
Just one line of code:
NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));
With .NET 4.0 you can do it like this:
<MenuItem Command="{Binding CommandName, Source={x:Reference ElementName}}"/>
精彩评论