Binding a context menu to a ListBox's Items co

2019-07-16 13:01发布

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

2条回答
狗以群分
2楼-- · 2019-07-16 13:30

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}}" >
查看更多
对你真心纯属浪费
3楼-- · 2019-07-16 13:38

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?

查看更多
登录 后发表回答