WPF DataGrid:为单个行动态生成的上下文菜单
WPF DataGrid: Dynamically-Generated ContextMenu for Individual Rows
我知道这个问题以前有人问过,但我无法用最少的代码示例来解决这个问题。我请求对整件事进行审查。
我有一个显示一堆行的 WPF DataGrid。每行都有一个带有自己命令的右键单击上下文菜单。
我无法正确设置 ContextMenu 部分。它抱怨“ContextMenu 不能有逻辑或视觉父级”。任何帮助将不胜感激。
谢谢。
XAML 文件:
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<!-- Begin uncertain part -->
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="x:Type ContextMenuItem">
<Setter Property="Command" Value="Binding Command}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
<!-- End uncertain part -->
<DataGrid.Columns>
<DataGridTemplateColumn Header="Module Name" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Module Description" Width="3*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.Description}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
视图模型文件:
public ObservableCollection<IModule> MyModules { get; set; }
// ...
public interface IModule
{
Configuration Configuration { get; }
void ExecuteCommand(Command command);
}
public class Configuration
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public List<Command> Commands = new List<Command>();
public Configuration(string name, string description, List<Command> commands)
{
Id = new Guid();
Name = name;
Description= description;
Commands = commands;
}
}
编辑 1:
我从很多地方得到了样本。现在它编译了。但是,右键单击上下文菜单完全是空的。
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Configuration Name" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.Name}">
<TextBlock.ContextMenu>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding ItemAction}" />
<Setter Property="Header" Value="{Binding ItemHeader}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Description" Width="3*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.MainMenuDescription}">
<TextBlock.ContextMenu>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding ItemAction}" />
<Setter Property="Header" Value="{Binding ItemHeader}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
虽然我不太喜欢第二种方法。我必须为每一列复制 ContextMenu 标记...
您可以定义一个 ItemContainerStyle
,在其中为所有行设置 ContextMenu
属性:
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type ContextMenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ItemContainerStyle>
<DataGrid.Columns>
...
</DataGrid.Columns>
</DataGrid>
我知道这个问题以前有人问过,但我无法用最少的代码示例来解决这个问题。我请求对整件事进行审查。
我有一个显示一堆行的 WPF DataGrid。每行都有一个带有自己命令的右键单击上下文菜单。
我无法正确设置 ContextMenu 部分。它抱怨“ContextMenu 不能有逻辑或视觉父级”。任何帮助将不胜感激。
谢谢。
XAML 文件:
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False"> <!-- Begin uncertain part --> <ContextMenu ItemsSource="{Binding Configuration.Commands}"> <ContextMenu.ItemContainerStyle> <Style TargetType="x:Type ContextMenuItem"> <Setter Property="Command" Value="Binding Command}" /> </Style> </ContextMenu.ItemContainerStyle> </ContextMenu> <!-- End uncertain part --> <DataGrid.Columns> <DataGridTemplateColumn Header="Module Name" Width="*" IsReadOnly="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Configuration.Name}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Header="Module Description" Width="3*" IsReadOnly="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Configuration.Description}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns>
视图模型文件:
public ObservableCollection<IModule> MyModules { get; set; } // ... public interface IModule { Configuration Configuration { get; } void ExecuteCommand(Command command); } public class Configuration { public Guid Id { get; private set; } public string Name { get; private set; } public string Description { get; private set; } public List<Command> Commands = new List<Command>(); public Configuration(string name, string description, List<Command> commands) { Id = new Guid(); Name = name; Description= description; Commands = commands; } }
编辑 1:
我从很多地方得到了样本。现在它编译了。但是,右键单击上下文菜单完全是空的。
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Configuration Name" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.Name}">
<TextBlock.ContextMenu>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding ItemAction}" />
<Setter Property="Header" Value="{Binding ItemHeader}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Description" Width="3*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Configuration.MainMenuDescription}">
<TextBlock.ContextMenu>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command" Value="{Binding ItemAction}" />
<Setter Property="Header" Value="{Binding ItemHeader}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
虽然我不太喜欢第二种方法。我必须为每一列复制 ContextMenu 标记...
您可以定义一个 ItemContainerStyle
,在其中为所有行设置 ContextMenu
属性:
<DataGrid ItemsSource="{Binding MyModules}" AutoGenerateColumns="False">
<DataGrid.ItemContainerStyle>
<Style TargetType="DataGridRow">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu ItemsSource="{Binding Configuration.Commands}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type ContextMenuItem}">
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ItemContainerStyle>
<DataGrid.Columns>
...
</DataGrid.Columns>
</DataGrid>