我有一个列表框,我正在为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>
我已经在ViewModel中编写了目标方法,如下所示。
public void DeleteGroup() { //ToDo
...
}
ViewModel被设置为UserControl的DataContext,其中有ListBox。
以上代码导致“找不到方法的目标”。我不知道为什么这不起作用。我也尝试过以下变化
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"
cal:Action.Target="{Binding ElementName=UCRelayDispositionView, Path=DataContext}">
其中UCRelayDispositionView是UserControl的名称。
为什么上面的代码不起作用?
修改:1 还尝试了以下
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"
cal:Action.TargetWithoutContext="{Binding ElementName=UCRelayDispositionView, Path=DataContext}">
和这个
<MenuItem Header="Remove Group" cal:Message.Attach="DeleteGroup"
cal:Action.TargetWithoutContext="{Binding ElementName=UCRelayDispositionView}">
编辑:2 我试图在ItemContainer上以下列方式使用Tag,但它也不起作用。
<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>
编辑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')
答案 0 :(得分:11)
您的问题在于您尝试将目标绑定到同一可视树中不存在的元素,例如您有一个项目所在的ContextMenu
。
要正确获取操作目标,您需要使用ContextMenu
s PlacementTarget
属性。
在X上查看关于XAML的以下答案
WPF Context Menus in Caliburn Micro
所以下面的XAML应该可以工作:
<MenuItem Header="Blah" cal:Message.Attach="SomeMethod()" cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}">
这应该在PlacementTarget
上查找ContextMenu
,并将操作的目标设置为PlacementTarget.Tag
的值(应该是ListBoxItem
)。
如果您将ListBoxItem.Tag
(正如您已经完成的那样)设置为父容器的DataContext
(ListBox
),那么您应该没问题
所以标签绑定应该是:
<Setter Property="Tag" Value="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"/>
e.g。整个事情应该是:
<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>
答案 1 :(得分:1)
添加到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>