我有一个
DataGrid
,我试图向其中添加一个带有命令绑定的 ContextMenu
。 ContextMenu
的定义如下:
<DataGrid Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="4" Name="DgResults" Margin="10, 25, 10,10" AutoGenerateColumns="False">
<DataGrid.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding GenerateDutyCycleCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
Header="Generate DC"></MenuItem>
</ContextMenu>
</DataGrid.ContextMenu>
</DataGrid>
在
Window
的代码隐藏中,我定义了命令属性:
private ICommand? _command;
public ICommand GenerateDutyCycleCommand
{
get
{
var m = 0;
return _command ??= new CommandHandler(GenerateDutyCycle, CanExecute);
}
}
public void GenerateDutyCycle()
{
MessageBox.Show("Command Executed");
var selectedItem = DgResults.SelectedItem;
var p = 0;
}
public bool CanExecute()
{
return Results.Count > 0;
}
在 XAML 中,如果我右键单击
GenerateDutyCycleCommand
并选择 转到定义,它会按预期转到属性,所以似乎一切都是正确的。
当我运行代码时,总是显示
ContextMenu
并且永远不会命中 CanExecute
方法。同样,如果我单击菜单项,则永远不会点击 GenerateDutyCycle
方法(或显示消息框)。我尝试了几次修改(例如,将 DataContext
的 MenuItem
设置为 Window
),但没有成功。
我在运行时还看到存在 XAML 绑定失败,其中指出 找不到源:RelativeSource FindAncestor、AncestorType='System.Windows.Window'、AncestorLevel='1'。我不清楚为什么这个绑定会失败,如果它可以识别定义(通过Go To Definition)。
任何帮助/指导将不胜感激。短暂性脑缺血发作。
更新:我能够通过从ContextMenu
中删除
DataGrid
定义并添加样式(到Window.Resources
)来使这个部分工作,如下所示:
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Tag"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}},
Path=DataContext}"/>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding PlacementTarget.Tag,
RelativeSource={RelativeSource Self}}">
<MenuItem Command="{Binding GenerateDutyCycleCommand}"
Header="Generate DC"></MenuItem>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
使用这种样式,当
DataGrid
中没有结果时,ContextMenu
不会显示。但是, CanExecute
和 GenerateDutyCycle
方法中的断点仍然没有被命中。另外,当有结果并单击菜单项时,不会显示 MessageBox
。
我设法通过添加
ContextMenu
作为 DataGrid
的资源,然后将其分配在行的样式中,如下所示找到解决方案:
<DataGrid.Resources>
<ContextMenu x:Key="CtxDataGrid">
<ContextMenu.Items>
<MenuItem
Header="Generate DC"
Command="{Binding GenerateDutyCycleCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}"/>
</ContextMenu.Items>
</ContextMenu>
</DataGrid.Resources>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Setter Property="ContextMenu" Value="{StaticResource CtxDataGrid}" />
</Style>
</DataGrid.RowStyle>