在ItemsControl.DataTemplate中为ContextMenu设置DataContext

doo*_*bop 5 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>
Run Code Online (Sandbox Code Playgroud)

Roh*_*ats 11

ContextMenu doesn't lie in same Visual Tree就像ItemsControl一样.因此,RelativeSource和ElementName将无法在Binding中工作,因为它们遍历Visual树以找到源.

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

x:Name在ItemsControl上设置并使用x:Reference如下绑定:

<ItemsControl x:Name="itemsControl">
   ....
   <MenuItem Command="{Binding DataContext.ClearAlarmsCommand,
                               Source={x:Reference itemsControl}}"
             Header="Clear All" />
   ....
</ItemControl>
Run Code Online (Sandbox Code Playgroud)

Freezable BindingProxy如果您的目标版本低于WPF 4.0,也可以使用方法.请参阅我在这里的答案.