WPF - 具有命令绑定的全局上下文菜单
WPF - Global Context Menu with Commands Binding
我想要一个可以在所有数据网格中使用的全局上下文菜单。我在 App.xaml 中定义了 ContextMenu 和样式。 Main Window 是用许多 UserControl 构建的。
<Application.Resources>
<ContextMenu x:Key="contextCommonMenu">
<MenuItem Header="Import from Excel" Command={???} />
<MenuItem Header="Export table to .csv file"/>
<MenuItem Header="Save to Database"/>
<MenuItem Header="Clear Data" />
<MenuItem Header="Synchronize with DB"/>
</ContextMenu>
<Style TargetType="DataGrid">
<Setter Property="ContextMenu" Value="{StaticResource contextCommonMenu}"/>
</Style>
</Application.Resources>
我的问题是如何将命令从 ViewModel 绑定到 ContextMenu?
如果 ContextMenu 是在 UI Control 中创建的,那么很简单,因为 Binding 看到了 ViewModel 但我无权访问 ViewModel?
这里的技巧是使用包含元素的 PlacementTarget 属性,ContextMenu 对齐到,在我们的例子中是什么 DataGrid。
但这只是解决方案的一半。由于数据模板,DataContext 被设置为数据项,而不是视图模型。所以你需要另一个相对源查找来找到视图模型。 Trick Number 2 是使用Tag 属性 将视图模型从外部绑定到网格,也就是上面使用的PlacementTarget。我们到了。
您始终可以通过遍历 Relative 源来设置上下文菜单。例如,您可以像下面这样设置上下文菜单的数据上下文:
<Application.Resources>
<ContextMenu x:Key="contextCommonMenu" DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Import from Excel" Command="{Binding MyCommand}"/>
<MenuItem Header="Export table to .csv file"/>
<MenuItem Header="Save to Database"/>
<MenuItem Header="Clear Data" />
<MenuItem Header="Synchronize with DB"/>
</ContextMenu>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="ContextMenu" Value="{StaticResource contextCommonMenu}"/>
</Style>
</Application.Resources>
现在,在您声明数据网格的视图中,您可以放置上下文菜单的标签以了解其绑定:
<DataGrid Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}" />
我希望这对你有用。上下文菜单将自动绑定到您在视图模型中定义的命令。
我想要一个可以在所有数据网格中使用的全局上下文菜单。我在 App.xaml 中定义了 ContextMenu 和样式。 Main Window 是用许多 UserControl 构建的。
<Application.Resources>
<ContextMenu x:Key="contextCommonMenu">
<MenuItem Header="Import from Excel" Command={???} />
<MenuItem Header="Export table to .csv file"/>
<MenuItem Header="Save to Database"/>
<MenuItem Header="Clear Data" />
<MenuItem Header="Synchronize with DB"/>
</ContextMenu>
<Style TargetType="DataGrid">
<Setter Property="ContextMenu" Value="{StaticResource contextCommonMenu}"/>
</Style>
</Application.Resources>
我的问题是如何将命令从 ViewModel 绑定到 ContextMenu?
如果 ContextMenu 是在 UI Control 中创建的,那么很简单,因为 Binding 看到了 ViewModel 但我无权访问 ViewModel?
这里的技巧是使用包含元素的 PlacementTarget 属性,ContextMenu 对齐到,在我们的例子中是什么 DataGrid。
但这只是解决方案的一半。由于数据模板,DataContext 被设置为数据项,而不是视图模型。所以你需要另一个相对源查找来找到视图模型。 Trick Number 2 是使用Tag 属性 将视图模型从外部绑定到网格,也就是上面使用的PlacementTarget。我们到了。
您始终可以通过遍历 Relative 源来设置上下文菜单。例如,您可以像下面这样设置上下文菜单的数据上下文:
<Application.Resources>
<ContextMenu x:Key="contextCommonMenu" DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Import from Excel" Command="{Binding MyCommand}"/>
<MenuItem Header="Export table to .csv file"/>
<MenuItem Header="Save to Database"/>
<MenuItem Header="Clear Data" />
<MenuItem Header="Synchronize with DB"/>
</ContextMenu>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="ContextMenu" Value="{StaticResource contextCommonMenu}"/>
</Style>
</Application.Resources>
现在,在您声明数据网格的视图中,您可以放置上下文菜单的标签以了解其绑定:
<DataGrid Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type Grid}}}" />
我希望这对你有用。上下文菜单将自动绑定到您在视图模型中定义的命令。