"Method target not found" thrown by Caliburn Message.Attach ()

I have a list box for which I set ItemContainer to enable the context menu. Here haml 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 encoded the target method in the ViewModel as shown below.

 public void DeleteGroup() { //ToDo ... } 

The ViewModel is set as a DataContext UserControl in which there is a ListBox.

The above code leads to an β€œnot found target for the method . I don’t know why this does not work. I 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 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 one

 <MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup" cal:Action.TargetWithoutContext="{Binding ElementName=UCRelayDispositionView}"> 

EDIT: 2 I tried using the tag as follows in the ItemContainer, but it does not 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') 
+7
source share
2 answers

Your problem is that you are trying to snap a target to an element that does not exist in the same visual tree, for example. you have ContextMenu item is on.

To get the target of the action correctly, you need to use the ContextMenu PlacementTarget property.

Check out the following answer for SO for XAML

WPF context menus in Caliburn Micro

So, the following XAML should work:

 <MenuItem Header="Blah" cal:Message.Attach="SomeMethod()" cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"> 

You need to look for a PlacementTarget on ContextMenu and set the target object to PlacementTarget.Tag (which should be a ListBoxItem ).

If you set ListBoxItem.Tag (as you already did) as the DataContext parent container ( ListBox ), you should be fine

therefore tag binding should be:

 <Setter Property="Tag" Value="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"/> 

eg. everything should be:

 <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="Tag" Value="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"/> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"> <MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup()" /> </ContextMenu> </Setter.Value> </Setter> </Style> </ListBox.ItemContainerStyle> 
+11
source

If you add an answer to Charleh, if you intend to use the same data context as the control, you can simply bind the DataContext instead of Tag . Makes it a little cleaner too.

 <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}" > <MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup()" /> </ContextMenu> </Setter.Value> </Setter> </Style> </ListBox.ItemContainerStyle> 
0
source

All Articles