How can I attach a Command with parameter to a *new* ContextMenu item?
I've attached commands to each of my context menu items as mentioned in other threads:
<StackPanel.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/LabelledFieldStyles.xaml" />
<ResourceDictionary>
<Style TargetType="{x:Type MenuItem}" x:Key="ContextMenuItemStyle">
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PetRegistry:RegistrationPanel}},Path=DataContext.CopyCommand}" />
<Setter Property="CommandParameter" Value="{Binding}" />
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</StackPanel.Resources>
<Label Name="copyPetContextTarget"
Content="(Right-click here to copy an existing pet's details)" Width="Auto">
<Label.ContextMenu>
<ContextMenu Name="copyPetMenu" ItemsSource="{Binding Pets}"
ItemContainerStyle="{StaticResource ContextMenuItemStyle}"
Visibility="Visible">
<ContextMenu.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
</Label.ContextMenu>
</Label>
The ItemsSource
is connected to Pets
, which is an ObservableCollection
. When I add a new pet, "Fluffy", it shows up in the list of context menu items. However, there's no command attached - selecting merely closes the menu without triggering the command.
Strangely, using a list instead of an ObservableCollection and notifying the relevant property change doesn't even cause the new pet to show up in the menu.
How can I make a new pet bind to the command when it's added? Or is this just a strange bug?
Edit: It's working fine for existing pets. The binding isn't necessarily the problem - it's only not attaching when a new pet is added to the list. I'm sure code-behind will work - I'm thinking that maybe there's some property I need to notify about, or some way of binding the command differently. Otherwise I'm just going to write some code-behind.
Edit2: Interesting! There's actually an error being output (silently as is the way with WPF) - it can't find the binding. Is there a different way of getting hold of that parent data context which might be simple开发者_开发百科r?
Edit3: @Yurec nailed it, but while this works manually, it fails for Microsoft UI Automation. Doh! So I've created a CopiablePet
object which has the CopyCommand embedded in it. Ugly, but it works. Will file a bug report with Microsoft if I get round to it as this is very silly.
Possible reason for such behaviour is because menu items are not in the same visual tree as PetRegistry:RegistrationPanel. Please try to replace Command binding to something like this
<Setter Property="Command" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}},Path=PlacementTarget.DataContext.CopyCommand}" />
Of course Label should contain the same DataContext as PetRegistry:RegistrationPanel.
I used in one of mine project something like this and it works for me:
<Style x:Key="FrameSubmenuItem" TargetType="MenuItem">
.....
....
<Setter Property="Command" Value="NavigationCommands.NavigateJournal"/>
<Setter Property="CommandTarget"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Menu}},
Path=TemplatedParent}"/>
<Setter Property="CommandParameter"
Value="{Binding RelativeSource={RelativeSource Self}}"/>
.....
...
Look on CommandTarget
use.
EDIT
Check the command binding by applying a Converter, at least for test reason, cause most likely, the binding of the command for new menu items somehow fails.
Hope this helps.
精彩评论