<DataTemplate x:Key="_ItemTemplateA">
<Grid Tag="{Binding Path=DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource ContentTemplateB}" Grid.Row="0" />
<ContentControl Name="uiContentPresenter" Content="{Binding ContentView}" Grid.Row="1" Height="0" />
<ContentControl DataContext="{Binding IsContentDisplayed}" DataContextChanged="IsDisplayed_Changed" Visibility="Collapsed" />
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="Text"
Command="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"
CommandParameter="{Binding}" />
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
字符串
上述数据模板应用于ItemsControl。问题是,对于为Grid指定的ContextMenu,PlacementTarget属性从未实际设置为任何内容,因此我无法访问Grid的Tag属性,该属性对于将应在父UserControl上执行的Command传递到上下文菜单是必要的。我基于类似的例子来实现这种方法,比如:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0244fbb0-fd5f-4a03-bd7b-978d7cbe1be3/
我找不到其他好的方法来传递这个命令。之所以这样设置,是因为我们使用的是MVVM方法,因此我们必须执行的命令位于应用此模板的用户控件的View Model中。我已经尝试过用几种不同的方法显式地设置PlacementTarget,但它仍然总是显示为未设置。
5条答案
按热度按时间vi4fp9gy1#
我意识到这是一个古老的问题,但似乎没有得到适当的回答。我看到了一个类似的帖子,并留下了完整的答案。您可能想看一看,因为您可以通过对代码进行一些调整来使其工作。
首先,将视图命名为
UserControl
...为了简单起见,我通常将我的所有代码命名为This
。然后记住我们的视图模型绑定到UserControl
的DataContext
,我们可以使用{Binding DataContext, ElementName=This}
绑定到视图模型。现在我们可以绑定到视图模型,我们必须将其与
ContextMenu.DataContext
连接起来。我使用对象的Tag
属性,并将ContextMenu
(PlacementTarget
)作为该连接,在本例中为Grid
:字符串
然后,我们可以通过将
ContextMenu.DataContext
属性绑定到PlacementTarget.Tag
属性(在我们的示例中是Grid
的属性)来访问ContextMenu
中的视图模型属性和命令:型
请注意
MenuItem.CommandTarget
属性上的绑定。设置此值可确保引发指定命令的目标元素是PlacementTarget
,在本例中是Grid
。还要注意
CommandParameter
绑定。它绑定到PlacementTarget
的DataContext
,或者在本例中绑定到Grid
。Grid
的DataContext
将从DataTemplate
继承,因此如果您使用ICommand
接口的某些实现,则您的数据项现在绑定到Command
中的object
参数:型
或者,如果你直接在视图模型中使用某种
RelayCommand
委托:型
rseugnpd2#
我们有同样的问题,但它的工作随机。contextmenu在controltemplate内,样式为列表框。我们尝试将contextmenu移动到模板内的不同级别,但发生了相同的错误。
我们认为这可能与刷新我们的ICollectionView有关,ICollectionView是ListBox的itemssource。
看起来当视图刷新时,在设置PlacementTarget之前,上下文菜单中的相对源绑定被评估。
感觉像是collectionviewsource或WPF的ContextMenu中的bug...
xpszyzbs3#
下面是一个基于您的测试用例的独立XAML示例:
ContextMenu
,使用Tag
从其PlacementTarget
的DataContext
检索Command
。您可以重新引入部分代码,直到它停止工作,以尝试找到问题所在:字符串
k10s72fa4#
在这个post中,
当您在按钮上单击鼠标右键时,ContextMenuService.PlacementTarget将填充。
它表示ContextMenu。当菜单显示时,PlacementTarget被填充。你可以通过snoop来检查。
编辑1这段代码运行良好。
字符串
yb3bgrhw5#
我知道这是一个老问题,但这个bug的有效解决方案是创建一个继承自
ContextMenu
的class
,然后添加一个新的DependencyProperty
,类型为PlacementMode
,名称为例如MenuPlacement,然后重写新菜单类的OnOpened
void,最后将MenuPlacement属性的值分配给原始Placement属性。