在ItemsControl.DataTemplate中为ContextMenu设置DataContext

时间:2014-07-29 16:41:31

标签: wpf

我有一个用于ItemsControl的数据模板的自定义控件。我想在每个项目上放置一个ContextMenu,让它调用UserControl的View Model来处理命令。使用下面的XAML,我可以在自定义控件上获取单击事件,以在用户控件视图模型中调用SelectedItemCommand。但是,使用上下文菜单的类似语法失败。默认情况下,我会为每个自定义控件获取视图模式。我使用的任何RelativeSource语法值都不会解析为用户控件的视图模型(RelativeSource Self)。

什么是神奇的代码?

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <controls:MyCustomItem Width="Auto"
                                                 Command="{Binding DataContext.SelectedItemCommand,
                                                                   RelativeSource={RelativeSource FindAncestor,
                                                                                                  AncestorType={x:Type ItemsControl}}}"
                                                 CommandParameter="{Binding}">
                    <controls:MyCustomItem.ContextMenu>
                        <ContextMenu>
                            <MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
                                                        RelativeSource={RelativeSource FindAncestor,
                                                                                       AncestorType={x:Type ItemsControl}}}"
                                      Header="Clear All" />
                        </ContextMenu>
                    </controls:MyCustomItem.ContextMenu>
                </controls:MyCustomItem>
            </DataTemplate>
        </ItemsControl.ItemTemplate>

1 个答案:

答案 0 :(得分:10)

ContextMenu doesn't lie in same Visual Tree 与ItemsControl相同。因此,RelativeSource和ElementName在Binding中不起作用,因为它们遍历Visual树以找到源。

如果您使用的是WPF 4.0或更高版本,则可以使用 x:Reference 标记扩展名与ItemsControl dataContext绑定。

在ItemsControl上设置x:Name并使用x:Reference进行绑定,如下所示:

<ItemsControl x:Name="itemsControl">
   ....
   <MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
                               Source={x:Reference itemsControl}}"
             Header="Clear All" />
   ....
</ItemControl>

如果您定位的版本低于WPF 4.0,也可以使用 Freezable BindingProxy 方法。有关该方法,请参阅我对here的回答。