[英]Binding collection to ContextMenu submenu
我在做一些看起來很容易但實際上並非如此的事情時遇到了麻煩。
我有一個 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 和 Playlists 都有一個 Name 屬性。
所以這兩個綁定之間存在某種沖突,我不知道如何解決。
預先感謝您的回復。
ContextMenu
與可視化樹分離,因此無法以正常方式在其范圍內與ElementName
或RelativeSource
綁定。 您需要一些代理技術來橋接切割。 這里我們有Freezable
元素,它可以繼承數據上下文,並且即使在這種情況下也可以輕松地綁定到可視化樹。 為方便起見,我們應該使用DiscreteObjectKeyFrame
因為它的 Value 可以接受所有類型的對象。 如果您關心名稱,那么您可以定義自己的自定義 Freezable 對象。
<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>
編輯- 這是為了幫助您了解如何混合播放列表和 SelectedFolder 中的信息:
<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
正上方)將其ItemsSource
設置為SelectedFolder.PlayableElements
。 ContextMenu
現在通過proxy
將其DataContext
設置為Window
實例。 因此,在其范圍內使用的所有綁定都沒有明確的Source
和RelativeSource
以及ElementName
集將獲得 DataContext(您的窗口)的解析源。
使用您展示的代碼,您只需將另一個菜單項綁定到 name 屬性。 我猜你要找的是MenuItem的ItemTemplate屬性。 通過這種方式,您可以定義應為該菜單項的每個子項顯示哪些數據。 檢查下面的標記:
<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.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Path=Name}" />
</DataTemplate>
</MenuItem.ItemTemplate>
<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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.