I have a list box for which I am styling ItemContainer to include a context menu. Here is the xaml for the same.
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
...
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
I have coded the target method in ViewModel as given below.
public void DeleteGroup() { //ToDo
...
}
The ViewModel is set as the DataContext of the UserControl in which there is the ListBox.
The above code results in "no target found for method". I am not sure why this doesn't work. I have also tried the following variation
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"
cal:Action.Target="{Binding ElementName=UCRelayDispositionView, Path=DataContext}">
where UCRelayDispositionView is the name of the UserControl.
Why does the above code do not work?
Edit: 1 Also tried the following
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"
cal:Action.TargetWithoutContext="{Binding ElementName=UCRelayDispositionView, Path=DataContext}">
and this
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"
cal:Action.TargetWithoutContext="{Binding ElementName=UCRelayDispositionView}">
EDIT: 2 I have tried to use the Tag in the following way on ItemContainer but it doesn't work either.
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Tag" Value="{Binding Path=DataContext, ElementName=UCRelayDispositionView}"/>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Remove Group"
cal:Message.Attach="DeleteGroup()"
cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}"/>
</ContextMenu>
</Setter.Value>
</Style>
</ListBox.ItemContainerStyle>
EDIT 3: Binding Errors
System.Windows.Data Error: 40 : BindingExpression path error: 'PlacementTarget' property not found on 'object' ''MenuItem' (Name='')'. BindingExpression:Path=PlacementTarget.Tag; DataItem='MenuItem' (Name=''); target element is 'MenuItem' (Name=''); target property is 'TargetWithoutContext' (type 'Object')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=UCRelayDispositionView'. BindingExpression:Path=DataContext; DataItem=null; target element is 'ContextMenu' (Name=''); target property is 'Tag' (type 'Object')
Adding to Charleh's answer, if you're going to be using the same data context as the control, then you can just bind the
DataContext
instead of aTag
. Makes it a bit cleaner too.Your problem lies in that you are trying to bind the target to an element which doesn't exist in the same visual tree e.g. you have a
ContextMenu
on which the item resides.To correctly get an action target, you need to use the
ContextMenu
sPlacementTarget
property.Check out the following answer on SO for the XAML
WPF Context Menus in Caliburn Micro
So the following XAML should work:
This should look for the
PlacementTarget
on theContextMenu
and set the target for the action to the value ofPlacementTarget.Tag
(which should be theListBoxItem
).If you set
ListBoxItem.Tag
(as you have already done) to be theDataContext
of the parent container (theListBox
) you should be okso the tag binding should be:
e.g. the whole thing should be: