将集合绑定到ContextMenu子菜单

时间:2015-10-09 14:41:26

标签: c# wpf data-binding

我在做一些看起来非常简单的事情时却遇到了麻烦,但事实并非如此。

我有一个ListView,其中我绑定了一个ObservableCollection,当我右键单击该ListView的一个元素时,我想要一个ContextMenu。

在那个ContextMenu中,我想要一个名为“添加到播放列表”的MenuItem,在其中,我想要所有播放列表的列表。

所以我做了这个,看起来对我来说是正确的:

<ListView Grid.Row="0" Grid.Column="1" x:Name="ListBoxSelectedFolder" ItemsSource="{Binding Path=SelectedFolder.PlayableElements}">
      <ListView.Resources>
        <ContextMenu x:Key="ContextMenu">
          <MenuItem Header="Add to" ItemsSource="{Binding Path=Playlists}">
            <MenuItem Header="{Binding Name}"/>
          </MenuItem>
          <MenuItem Header="Remove from All" />
        </ContextMenu>
      <Style TargetType="{x:Type ListViewItem}">
         <Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/>
    </Style>
      </ListView.Resources>
      <ListView.View>
        <GridView>
            <GridViewColumn Header="Type" DisplayMemberBinding="{Binding Extension}" />
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" />
        </GridView>
    </ListView.View>
</ListView>

问题是我在子菜单中唯一得到的是我点击的项目的名称:不知何故,它与ListView,SelectedFolder.PlayableElements的集合绑定,因为SelectedFolder.PlayableElements和播放列表都有一个名称属性。

因此两个绑定之间存在某种冲突,我不知道如何解决它。

提前感谢您的回复。

1 个答案:

答案 0 :(得分:1)

struct MyDataNode { MyDataNode* rbe_left; MyDataNode* rbe_ight; char rbe_color; // data to be stored }; template <class Entry> class RbTree { // implementation }; // usage: RbTree<MyDataNode> treeInstance; 与可视树分离,因此无法以正常方式在其范围内使用ContextMenuElementName进行绑定。你需要一些代理技术来弥补切割。这里我们有RelativeSource元素,它可以继承数据上下文,并允许绑定到可视化树,即使在这种情况下也很容易。为方便起见,我们应该使用Freezable因为它的Value可以接受所有类型的对象。如果您关心名称,那么您可以定义自己的自定义Freezable对象。

DiscreteObjectKeyFrame

修改 - 这是为了帮助您了解如何混合播放列表和SelectedFolder中的信息:

<ListView Grid.Row="0" Grid.Column="1" x:Name="ListBoxSelectedFolder" ItemsSource="{Binding Path=SelectedFolder.PlayableElements}">
  <ListView.Resources>
    <DiscreteObjectKeyFrame x:Key="proxy" Value="{Binding Playlists, RelativeSource={RelativeSource AncestorType=Window}}"/>
    <ContextMenu x:Key="ContextMenu">
      <MenuItem Header="Add to" ItemsSource="{Binding Value, Source={StaticResource proxy}}">
         <MenuItem.ItemTemplate>
             <DataTemplate>
                 <TextBlock Text="{Binding Name}"/>
             </DataTemplate>
         </MenuItem.ItemTemplate>
      </MenuItem>
      <MenuItem Header="Remove from All" />
    </ContextMenu>
    <Style TargetType="{x:Type ListViewItem}">
     <Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/>
    </Style>
  </ListView.Resources>
  <!-- ... -->
</ListView>

如您所见,添加的菜单项(<ListView Grid.Row="0" Grid.Column="1" x:Name="ListBoxSelectedFolder" ItemsSource="{Binding Path=SelectedFolder.PlayableElements}"> <ListView.Resources> <DiscreteObjectKeyFrame x:Key="proxy" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/> <ContextMenu x:Key="ContextMenu" DataContext="{Binding Value, Source={StaticResource proxy}}"> <MenuItem Header="Add to" ItemsSource="{Binding Playlists}"> <MenuItem.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}"/> </DataTemplate> </MenuItem.ItemTemplate> </MenuItem> <MenuItem Header="Playable elements" ItemsSource="{Binding SelectedFolder.PlayableElements}"/> <MenuItem Header="Remove from All" /> </ContextMenu> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/> </Style> </ListView.Resources> <!-- ... --> </ListView> 正上方)的Remove from all设置为ItemsSourceSelectedFolder.PlayableElements现在通过ContextMenuDataContext设置为Window个实例。因此,在没有明确proxySourceRelativeSource设置的范围内使用的所有Binding都将获得DataContext(您的窗口)的已解析源。