wpf Caliburn Message.Attach() 抛出的“找不到方法的目标”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13587368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"No target found for method" thrown by Caliburn Message.Attach()
提问by Jatin
I have a list box for which I am styling ItemContainer to include a context menu. Here is the xaml for the same.
我有一个列表框,我正在为其设置 ItemContainer 样式以包含上下文菜单。这是相同的xaml。
<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.
我已经在 ViewModel 中对目标方法进行了编码,如下所示。
public void DeleteGroup() { //ToDo
...
}
The ViewModel is set as the DataContext of the UserControl in which there is the ListBox.
ViewModel 被设置为其中有 ListBox 的 UserControl 的 DataContext。
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.
其中 UCRelayDispositionView 是 UserControl 的名称。
Why does the above code do not work?
为什么上面的代码不起作用?
Edit: 1Also tried the following
编辑:1还尝试了以下
<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: 2I have tried to use the Tag in the following way on ItemContainer but it doesn't work either.
编辑:2我试图在 ItemContainer 上以下列方式使用标签,但它也不起作用。
<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
编辑 3:绑定错误
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')
回答by Charleh
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 ContextMenuon which the item resides.
您的问题在于您试图将目标绑定到同一可视化树中不存在的元素,例如您有一个ContextMenu项目所在的元素。
To correctly get an action target, you need to use the ContextMenus PlacementTargetproperty.
要正确获取操作目标,您需要使用ContextMenusPlacementTarget属性。
Check out the following answer on SO for the XAML
查看有关 XAML 的 SO 的以下答案
WPF Context Menus in Caliburn Micro
So the following XAML should work:
所以下面的 XAML 应该可以工作:
<MenuItem Header="Blah" cal:Message.Attach="SomeMethod()" cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}">
This should look for the PlacementTargeton the ContextMenuand set the target for the action to the value of PlacementTarget.Tag(which should be the ListBoxItem).
这应该在PlacementTarget上查找ContextMenu并将操作的目标设置为值PlacementTarget.Tag(应该是ListBoxItem)。
If you set ListBoxItem.Tag(as you have already done) to be the DataContextof the parent container (the ListBox) you should be ok
如果您设置ListBoxItem.Tag(正如您已经完成的那样)成为DataContext父容器(the ListBox)的 ,您应该没问题
so the tag binding should be:
所以标签绑定应该是:
<Setter Property="Tag" Value="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"/>
e.g. the whole thing 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>
回答by Kao
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 DataContextinstead of a Tag. Makes it a bit cleaner too.
添加到Charleh的答案,如果你将要使用的控制同样的数据情况下,那么你可以绑定DataContext的,而不是一个Tag。也让它更干净一些。
<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>

