C# DataGridView是否可以像WinForms中的UI那样用于完成下表?

C# DataGridView是否可以像WinForms中的UI那样用于完成下表?,c#,winforms,visual-studio-2010,datagridview,C#,Winforms,Visual Studio 2010,Datagridview,这是个麻烦,但我一直在使用TableLayoutPanel来显示一些数据,如下面的屏幕截图所示。但有几次有人建议,使用DataGridView可以轻松完成这项工作 所以我的问题是,下面的屏幕截图可以在Windows窗体中使用DataGridView完成吗?我在网上搜索过,没有找到与下面类似的东西 答案是“是的,可以。”或“不,不可能。”。但是请不要发布替代方案,因为问题的目的是最终知道类似的事情是否可以通过DataGridView实现 DataTable如下所示: BG_Color Emp

这是个麻烦,但我一直在使用
TableLayoutPanel
来显示一些数据,如下面的屏幕截图所示。但有几次有人建议,使用
DataGridView
可以轻松完成这项工作

所以我的问题是,下面的屏幕截图可以在Windows窗体中使用
DataGridView
完成吗?我在网上搜索过,没有找到与下面类似的东西

答案是“是的,可以。”或“不,不可能。”。但是请不要发布替代方案,因为问题的目的是最终知道类似的事情是否可以通过
DataGridView
实现

DataTable
如下所示:

BG_Color    EmpId     ColNum    RowNum
Yellow      4304      1         1
Yellow      8464      2         1
Yellow      2012      3         1
Blue        4593      1         2
Blue        3515      2         2
Blue        0546      3         2
Green       4346      1         3
Green       5426      2         3
Green       0551      3         3
结果如下。此处仅显示,不可单击任何内容:

使用
DataGridView
如何实现这一点?我甚至通过
RowNum
ColNum
列出了每个单元格的确切位置,以防需要

或者,如果有人可以分享类似的链接,我们将不胜感激


谢谢。

是的,您可以使用
DataGridView
创建这样的用户界面:

  • 您可以手动设置网格的
    RowCount
    ColumnCount
  • 您可以删除
    DataGridView
    CellFormatting
    事件,并在其中设置单元格的值和背景色
  • 不能对当前数据结构使用数据绑定
下面是一个示例数据:

DataTable table;
private void Form1_Load(object sender, EventArgs e)
{
    table = GetData();
    this.dataGridView1.AllowUserToAddRows = false;
    this.dataGridView1.AllowUserToDeleteRows = false;
    this.dataGridView1.ReadOnly = true;
    this.dataGridView1.RowHeadersVisible = false;
    this.dataGridView1.ColumnHeadersVisible = false;
    this.dataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect;
    this.dataGridView1.RowTemplate.Height = 64;
    this.dataGridView1.CellFormatting += dataGridView1_CellFormatting;
    this.dataGridView1.ColumnCount = (int)table.Compute("Max(ColNum)", "");
    this.dataGridView1.RowCount = (int)table.Compute("Max(RowNum)", "");
}
void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    if (e.RowIndex >= 0 & e.ColumnIndex >= 0)
    {
        var row = table.Select(string.Format("RowNum={0} AND ColNum={1}",
            e.RowIndex + 1, e.ColumnIndex + 1)).FirstOrDefault();
        if (row != null)
        {
            e.Value = row["EmpId"];
            var color = (Color)new ColorConverter().ConvertFrom(row["BG_Color"]);
            e.CellStyle.BackColor = color;
            e.CellStyle.SelectionBackColor = color;
            e.CellStyle.SelectionForeColor = Color.Black;
            e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        }
    }
}

正如我在对问题的评论中提到的,实现这一点很容易,但只有一个条件:数据表中存储的数据必须进行数据透视。怎么用?请看一个例子:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        //create DataTable
        DataTable dt = CreateCustomDataTable();
        var pivotDt = dt.AsEnumerable()
        .GroupBy(x => x.Field<int>("RowNum"))
        .Select(grp => new
        {
            BG_Color = grp.First().Field<string>("BG_Color").ToLower(), //System.Drawing.Color.FromName(grp.First().Field<string>("BG_Color")),
            Emp1 = grp.Where(e => e.Field<int>("ColNum") == 1).Select(a => a.Field<int>("EmpId")).SingleOrDefault(),
            Emp2 = grp.Where(e => e.Field<int>("ColNum") == 2).Select(a => a.Field<int>("EmpId")).SingleOrDefault(),
            Emp3 = grp.Where(e => e.Field<int>("ColNum") == 3).Select(a => a.Field<int>("EmpId")).SingleOrDefault()
        }).ToList();
        dataGridView1.DataSource = pivotDt;
        dataGridView1.Columns[0].Visible = false;

    }

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        DataGridView dgv = (DataGridView)sender;
        e.CellStyle.BackColor = Color.FromName(dgv.Rows[e.RowIndex].Cells[0].Value.ToString());
        e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        e.CellStyle.SelectionBackColor = Color.Transparent;
    }
//...
}
公共部分类表单1:表单
{
公共表格1()
{
初始化组件();
//创建数据表
DataTable dt=CreateCustomDataTable();
var pivotDt=dt.AsEnumerable()
.GroupBy(x=>x.Field(“RowNum”))
.选择(grp=>new
{
BG_Color=grp.First().Field(“BG_Color”).ToLower(),//System.Drawing.Color.FromName(grp.First().Field(“BG_Color”),
Emp1=grp.Where(e=>e.Field(“ColNum”)==1)。选择(a=>a.Field(“EmpId”)。SingleOrDefault(),
Emp2=grp.Where(e=>e.Field(“ColNum”)==2)。选择(a=>a.Field(“EmpId”)。SingleOrDefault(),
Emp3=grp.Where(e=>e.Field(“ColNum”)==3)。选择(a=>a.Field(“EmpId”)。SingleOrDefault()
}).ToList();
dataGridView1.DataSource=pivotDt;
dataGridView1.Columns[0]。Visible=false;
}
私有void dataGridView1_CellFormatting(对象发送方,DataGridViewCellFormattingEventArgs e)
{
DataGridView dgv=(DataGridView)发送方;
e、 CellStyle.BackColor=Color.FromName(dgv.Rows[e.RowIndex].Cells[0].Value.ToString());
e、 CellStyle.Alignment=DataGridViewContentAlignment.MiddleCenter;
e、 CellStyle.SelectionBackColor=Color.Transparent;
}
//...
}
结果:

对于如此数量的数据,性能损失的风险等于零

关于您的主要问题的最后一个注释

(…)以下屏幕截图可以在Windows窗体中使用datagridview完成吗

答案可能是肯定的,也可能是否定的,这是不可能的。(……)


是的。这是可能的-非常容易。

是的,但是。。。。您需要使用自己的格式,如行高、背景色等。行高是任意的;它可以是任何高度。背景色在datatable中。请查看或。@MaciejLos,问题不是如何将数据绑定到
DataGridView
。你的链接能完成你在截图中看到的吗?@MaciejLos不,完全正确。查看示例数据的行计数。它有9行。如果你需要数据绑定,数据结构应该改变。我个人更喜欢使用
TableLayoutPanel
来处理如此大量的数据和这样的UI。这篇文章只是想回答你的问题,datagridview可以在winform中实现以下功能吗?看来
TableLayoutPanel
确实是更好的选择。我这样问是因为每次我发布关于
TableLayoutPanel
的内容时,总有人评论说使用
DataGridView
是多么容易。从这段代码和其他人发布的链接来看,这并不容易。是的,在这种情况下,
TableLayoutPanel
是更好的选择。我正在查看datagridview的代码,使用示例数据,它看起来相当不错。您的答案是否要求数据表中的ColNum和RowNum都起作用?行的总数总是相同的(3),我可以使用
(int)table.Compute(“Max(ColNum)”,”)包含ColNum使列编号动态,与行编号相同。如果您知道for column count适用于exmaple 3,则可以使用3。但我更喜欢继续使用
Max
。我知道这是可能的,但大部分工作都将用于尝试将数据适配到datagridview中。例如,从我所看到的,似乎我需要事先知道有多少列。如果有4列而不是3列,会发生什么?有没有一种方法可以动态添加列?嗯。。。有一种方法可以动态添加列,但这会有点困难。。。你对动态版本感兴趣吗?如果可能的话,是的。我总是知道会有多少行,但列是动态的。再次感谢。@MaciejLos可能对OP有一些新的了解,例如对数据表使用Linq查询。它证实了我所说的,在不改变数据结构的情况下,不能使用数据绑定您应该在每次加载数据后重新创建透视。-你应该让你的轴支持动态列此外,您正在使用相同的
CellFormatting
事件。那是什么