【问题标题】:Is it possible to switch rows and columns in a datagridview?是否可以在 datagridview 中切换行和列?
【发布时间】:2010-10-25 14:48:09
【问题描述】:

我在 DataTable 中有 10 条数据记录,其中包含 3 个字段“Foo”、“Bar”和“Baz”。

如果我将它连接到 DataGridView 中,我会看到 10 行和 3 列,并且列标题会显示字段的名称。

我想知道反转行和列是多么容易,因此对于相同的数据,我最终得到 3 行和 10 列,并且字段名称显示在行标题中。


我可以手动做一些事情,比如重写 OnPaint 方法并将字段名称直接绘制到行标题单元格中,但我正在寻找更自动化的东西。

再次,建议手动交换值,但除非我将所有值都设为字符串,否则这是行不通的。数据表中的 3 列 - int、float 和 string 类型的 Foo、Bar 和 Baz 不会转置。

即使我管理了所有这些手动更改,我的数据网格也有 CheckBox 列、ComboBox 列 - 不存在这样的行对应项 - 没有 CheckBox 行或 ComboBox 行。我目前只需要告诉编译器“添加一个 ComboBoxColumn”我必须重新编写,以便单独生成每个单元格。

理想情况下,我想要一个 TransposableDataGridView,它公开了 DataGridView 的所有功能,并带有一个额外的 bool 属性“Transposed”。这样我就可以让我的所有代码保持原样 - 除了网格的类型之外,我不需要更改任何内容。

如果不存在这样的东西,我可能只需要去写它。 (应该只需要我一年左右的时间!:)

【问题讨论】:

标签: c# winforms datagridview


【解决方案1】:

您可以创建新的 DataTable,添加适当数量的列,然后将值从一个表复制到另一个表,只需交换行和列。

我认为您不能像设置列标题一样设置行标题(或者至少我不知道如何),因此您可以将字段名称放在单独的列中。

DataTable oldTable = new DataTable();

...

DataTable newTable = new DataTable();

newTable.Columns.Add("Field Name");
for (int i = 0; i < oldTable.Rows.Count; i++)
    newTable.Columns.Add();

for (int i = 0; i < oldTable.Columns.Count; i++)
{
    DataRow newRow = newTable.NewRow();

    newRow[0] = oldTable.Columns[i].Caption;
    for (int j = 0; j < oldTable.Rows.Count; j++)
        newRow[j+1] = oldTable.Rows[j][i];
    newTable.Rows.Add(newRow);
}

dataGridView.DataSource = newTable;

【讨论】:

  • 感谢您的回答 - 如果我有一个 bool DataColumn 和一个字符串 DataColumn 会发生什么 - 我将转置网格的列设为什么类型?
  • 如果不设置类型,默认为字符串,所以如果你只是想把数据展示给用户就可以了,因为其他类型的值会自动转换。另一种可能性是将类型设置为对象。这种类型的变量可以包含任何东西。
【解决方案2】:

我使用 Developer Express 垂直网格.. 这就像你想要一个旋转的网格。 它还允许每行使用不同的编辑器。

Link to vertical grid product page

【讨论】:

    【解决方案3】:

    您可以通过以编程方式添加所需的列数(例如,增加 7 列以达到 10)然后以编程方式将 row、col 与 col、row 交换来做到这一点。

    【讨论】:

    • 您是建议将列添加到 DataTable 还是 DataGridView?
    【解决方案4】:

    将 LayoutTransform 应用到 DataGrid:

    <DataGrid Name = "reverseThis">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Top" Binding="{Binding Path=Top}"/>
            <DataGridTextColumn Header="Middle" Binding="{Binding Path=Middle}"/>
            <DataGridTextColumn Header="Bottom" Binding="{Binding Path=Bottom}"/>
        </DataGrid.Columns>
        <DataGrid.LayoutTransform>
            <TransformGroup>
                <RotateTransform Angle="-90"/>
                <ScaleTransform ScaleX="1" ScaleY="-1" />
            </TransformGroup>
        </DataGrid.LayoutTransform>
    

    您还需要反转列标题:

    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="{x:Type DataGridColumnHeader}"
                                       BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <TransformGroup>
                        <RotateTransform Angle="-90"/>
                        <ScaleTransform ScaleX="1" ScaleY="-1" />
                    </TransformGroup>
                </Setter.Value>
            </Setter>
            <Setter Property="FontWeight" Value="Bold"></Setter>
        </Style>
    </DataGrid.ColumnHeaderStyle>
    

    还有细胞,否则它们会镜像和旋转出来:

        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell" >
                <Setter Property="LayoutTransform">
                    <Setter.Value>
                        <TransformGroup>
                            <RotateTransform Angle="-90"/>
                            <ScaleTransform ScaleX="1" ScaleY="-1" />
                        </TransformGroup>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.CellStyle>
    
    </DataGrid>
    

    【讨论】:

    • 我意识到最初的问题是关于 DataGridView 但我的答案是针对 DataGrid。这篇文章是“数据网格交换行和列”的第一个谷歌点击,所以我会留下它。
    【解决方案5】:

    在我的情况下,还需要为新表的所有列添加名称。我写了一个函数来生成这样的转置表:

    static public DataTable Transpose(DataTable inputTable, List<string> newColumnNames)
    {
        DataTable outputTable = new DataTable();
    
        ///You should also verify if newColumnsNames.Count matches inputTable number of row
    
        //Creates the columns, using the provided column names.
        foreach (var newColumnName in newColumnNames)
        {
            outputTable.Columns.Add(newColumnName, typeof(string));
        }
    
        foreach (DataColumn inputColumn in inputTable.Columns)
        {
            //For each old column we generate a row in the new table
            DataRow newRow = outputTable.NewRow();
    
            //Looks in the former header row to fill in the first column
            newRow[0] = inputColumn.ColumnName.ToString();
    
            int counter = 1;
            foreach (DataRow row in inputTable.Rows)
            {
                newRow[counter] = row[inputColumn.ColumnName].ToString();
                counter++;
            }
            outputTable.Rows.Add(newRow);
        }
    
        return outputTable;
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-05
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 2022-01-04
      相关资源
      最近更新 更多