7
votes

I have a user control with a ListView containing simple items from an ObservableCollection. I would like the ContextMenu of that ListView to contain items depending on what's selected in the ListView. If no item is selected, some MenuItems should not be visible.

My converter isn't even called when I open the ContextMenu. The binding seems to be wrong, I find this in the output window:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=listView'. BindingExpression:Path=SelectedItem; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Visibility' (type 'Visibility')

I don't understand what's wrong and could not figure it out by searching the web.

Here is some simplified code:

<UserControl x:Class="MyApp.DatabaseControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:MyApp"
Height="Auto" 
Width="Auto">

<UserControl.Resources>
    <l:ValueToVisibilityConverter x:Key="valueToVisibility" />
</UserControl.Resources>

<Grid>
    <ListView x:Name="listView" ItemsSource="{Binding Persons}">
        <ListView.View>
            <GridView>
                <GridViewColumn Width="140" Header="First Name" DisplayMemberBinding="{Binding FirstName}"/>
                <GridViewColumn Width="140" Header="Last Name" DisplayMemberBinding="{Binding LastName}" />
            </GridView>
        </ListView.View>

        <ListView.ContextMenu>
            <ContextMenu>
                <MenuItem 
                    Header="Open" 
                    Visibility="{Binding SelectedItem, ElementName=listView, Converter={StaticResource valueToVisibility}}"/>
                <Separator/>
                <MenuItem Header="Add..."/>
                <MenuItem Header="Remove"/>
            </ContextMenu>
        </ListView.ContextMenu>
    </ListView>
</Grid>

Thanks a lot!

1

1 Answers

7
votes

The problem is that the ContextMenu is not in the same visual tree as the ListBox, therefore bindings don't find the ListBox. If you bind against PlacementTarget, that should do the trick:

<MenuItem Header="Open"
    Visibility="{Binding RelativeSource={RelativeSource FindAncestor,
        AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem,
        Converter={StaticResource valueToVisibility}}" />