【问题标题】:WPF DataGrid: Dynamically-Generated ContextMenu for Individual RowsWPF DataGrid:为各个行动态生成的 ContextMenu
【发布时间】:2020-09-21 21:59:55
【问题描述】:

我知道以前有人问过这个问题,但我无法使用最少的代码示例。我要求对整个事情进行审查。

我有一个显示一堆行的 WPF DataGrid。每行都有一个右键单击 ContextMenu 及其自己的命令。

我无法正确设置 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>
    
  • ViewModel 文件:

      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 标记...

【问题讨论】:

  • 尝试在您的 {Binding Configuration.Commands} 中添加一些虚拟转换器,看看您实际得到了什么。可能是你什么都没有(也许你初始化你的集合较晚并且你没有实现 INotifyPropertyChanged),或者你的 ContextMenu 不共享 TextBlock 的 DataContext。
  • @o_w:谢谢你的建议。 DataContext 很好,ViewModel 是正确的。这只是我正在寻找的一些 XAML 语法。 mm8 通过 ItemContainerStyle 方法为我解决了这个问题。

标签: wpf xaml dynamic datagrid contextmenu


【解决方案1】:

您可以定义一个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>

【讨论】:

  • 谢谢。有用。我只需要在第 8 行稍作调整。我将它从 [
猜你喜欢
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2010-12-31
  • 1970-01-01
相关资源
最近更新 更多