Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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}"/>
                            <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?

like image 248
Klaus Nji Avatar asked Apr 11 '10 13:04

Klaus Nji


3 Answers

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

  1. Use RoutedUICommands with a command binding on the UserControl, then no binding is needed.
  2. 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}"

  3. (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.

like image 128
Aran Mulholland Avatar answered Nov 03 '22 23:11

Aran Mulholland


Best solution here ElementName Binding from MenuItem in ContextMenu

Just one line of code:

NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));
like image 44
b0bi Avatar answered Nov 04 '22 00:11

b0bi


With .NET 4.0 you can do it like this:

<MenuItem Command="{Binding CommandName, Source={x:Reference ElementName}}"/>
like image 6
Jonas Avatar answered Nov 04 '22 00:11

Jonas