views:

680

answers:

2

Hello,

I'm trying to create a context menu for a list box which displays elements in the context menu from the list box. I am able to accomplish this by using the following XAML:

<Window.Resources>        
    <ContextMenu x:Key="contextMenu" 
                 ItemsSource="{Binding Items, 
        RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" >
        <ContextMenu.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Content}"/>
            </DataTemplate>
        </ContextMenu.ItemTemplate>
    </ContextMenu>

    <Style TargetType="{x:Type ListBox}">
        <Setter Property="ContextMenu" Value="{StaticResource contextMenu}"/>            
    </Style>
</Window.Resources>

This works great for one list box. However, when I have a second list box, the context menu keeps showing the elements from the first list box. In other words, the ItemsSource of the context menu does not change. Only the first time that the context menu is opened is the ItemsSource property set. For example:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <ListBox x:Name="first" >
        <ListBoxItem>First 1</ListBoxItem>
        <ListBoxItem>First 2</ListBoxItem>
        <ListBoxItem>First 3</ListBoxItem>
        <ListBoxItem>First 4</ListBoxItem>
        <ListBoxItem>First 5</ListBoxItem>
    </ListBox>
    <ListBox x:Name="second" Grid.Column="2" >
        <ListBoxItem>Second 1</ListBoxItem>
        <ListBoxItem>Second 2</ListBoxItem>
        <ListBoxItem>Second 3</ListBoxItem>
        <ListBoxItem>Second 4</ListBoxItem>
        <ListBoxItem>Second 5</ListBoxItem>
    </ListBox>    
</Grid>

I would like to set the context menu in a Style because I have many instances of a listbox and do not want to define a separate context menu for each listbox.

UPDATE: I finally figured out how to fix it. I just need to bind to the PlacementTarget.Items and using a self relative source instead of using a find ancestor relative source.

<ContextMenu x:Key="contextMenu" 
  ItemsSource="{Binding PlacementTarget.Items, 
  RelativeSource={RelativeSource Self}}" >
A: 

I think the issue you're having here is due to the fact that the context menu is part of a different visual tree. That is, you cannot find the ListBox ancestor because it is not actually an ancestor of the context menu.

If you look at the debug panel of Visual Studio, you should see some warnings about the failing binding expression. Do you?

Drew Noakes
There are no failing binding warnings.
Pavel
A: 

Found the answer, I just need to bind to the PlacementTarget.Items and using a self relative source instead of using a find ancestor relative source.

<ContextMenu x:Key="contextMenu" 
  ItemsSource="{Binding PlacementTarget.Items, 
  RelativeSource={RelativeSource Self}}" >
Pavel