使用 C# 合并 DatagridView 中的多行标题

Mr.*_*ean 2 c# merge datagridview winforms

我有一个项目,我需要从数据库查看 Datagridview 中的数据,它应该看起来像甘特图。

我想让 Datagridview 看起来像这样:

数据网格视图示例

我已经尝试了很多来自互联网的代码,但没有一个能正常工作

例如这个: https: //social.msdn.microsoft.com/Forums/windows/en-US/87004d70-482a-4b86-ba18-371670254b6a/how-to-merge-headers-in-a-datagridview ?forum =winforms数据控件

我也不知道如何将日期值放入单元格/行标题中

这就是我如何获取一个月中的天数

int year = DateTime.Now.Year;
int Jan = 1;
int daysInJan = System.DateTime.DaysInMonth(year, Jan);
Run Code Online (Sandbox Code Playgroud)

OhB*_*ise 6

链接的解决方案对于它提供的示例运行良好。那是说:

我无法在一个标题下获得超过 2 列的内容

根据我们在评论中的讨论,我认为只需添加额外的列宽即可将“主”标题拉伸到超过 2 列。这很好,直到我用足够的列进行测试以允许水平滚动。就在那时,我注意到只有当该月的第一天栏可见时才会显示该月的“主”标题

以下代码将解决这些问题:

  1. 延伸超过 2 个以上的列。
  2. 通过调整大小显示“主”标题,无论第一可见性如何。
  3. 如何将日期值放入单元格/行标题中

  4. 对象的一般清理IDisposable和重构。

在表单中,要设置网格,请执行以下操作:

private int[] daysInMonths;

private void Form1_Load(object sender, EventArgs e)
{
    int year = DateTime.Now.Year;
    daysInMonths = new int[12];

    // Add a column for each day of the year; where
    // column name = the date (creates all unique column names)
    // column header text = the numeric day of the month
    for (int month = 1; month <= 12; month++)
    {
        daysInMonths[month - 1] = DateTime.DaysInMonth(year, month);

        // for days 1-31, 1-29, etc.
        for (int day = 1; day <= daysInMonths[month - 1]; day++)
        {
            DateTime date = new DateTime(year, month, day);
            DataGridViewTextBoxColumn col = new DataGridViewTextBoxColumn()
            {
                Name = date.ToString(),
                HeaderText = day.ToString(),
                Width = 20
            };

            this.dataGridView1.Columns.Add(col);
        }
    }

    // add some default rows
    for (int r = 0; r < 4; r++)
    {
        DataGridViewRow row = new DataGridViewRow();
        row.CreateCells(this.dataGridView1);
        row.HeaderCell.Value = $"Project {r + 1}";
        this.dataGridView1.Rows.Add(row);
    }

    this.dataGridView1.AllowUserToAddRows = false;
    this.dataGridView1.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders;
    this.dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
    this.dataGridView1.ColumnHeadersHeight = this.dataGridView1.ColumnHeadersHeight * 2;
    this.dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;

    this.dataGridView1.Paint += DataGridView1_Paint;
    this.dataGridView1.Scroll += DataGridView1_Scroll;
    this.dataGridView1.ColumnWidthChanged += DataGridView1_ColumnWidthChanged;
    this.dataGridView1.Resize += DataGridView1_Resize;
}
Run Code Online (Sandbox Code Playgroud)

然后添加您的事件处理程序:

private void InvalidateHeader()
{
    Rectangle rtHeader = this.dataGridView1.DisplayRectangle;
    rtHeader.Height = this.dataGridView1.ColumnHeadersHeight / 2;
    this.dataGridView1.Invalidate(rtHeader);
}

private void DataGridView1_Resize(object sender, EventArgs e)
{
    this.InvalidateHeader();
}

private void DataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
    this.InvalidateHeader();
}

private void DataGridView1_Scroll(object sender, ScrollEventArgs e)
{
    this.InvalidateHeader();
}

private void DataGridView1_Paint(object sender, PaintEventArgs e)
{
    int col = 0;

    // For each month, create the display rectangle for the main title and draw it.
    foreach (int daysInMonth in daysInMonths)
    {
        Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(col, -1, true);

        // Start the rectangle from the first visible day of the month,
        // and add the width of the column for each following day.
        for (int day = 0; day < daysInMonth; day++)
        {
            Rectangle r2 = this.dataGridView1.GetCellDisplayRectangle(col + day, -1, true);

            if (r1.Width == 0) // Cell is not displayed.
            {
                r1 = r2;
            }
            else
            {
                r1.Width += r2.Width;
            }
        }

        r1.X += 1;
        r1.Y += 1;
        r1.Height = r1.Height / 2 - 2;
        r1.Width -= 2;

        using (Brush back = new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor))
        using (Brush fore = new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor))
        using (Pen p = new Pen(this.dataGridView1.GridColor))
        using (StringFormat format = new StringFormat())
        {
            string month = DateTime.Parse(this.dataGridView1.Columns[col].Name).ToString("MMMM");

            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            e.Graphics.FillRectangle(back, r1);
            e.Graphics.DrawRectangle(p, r1);
            e.Graphics.DrawString(month, this.dataGridView1.ColumnHeadersDefaultCellStyle.Font, fore, r1, format);
        }

        col += daysInMonth; // Move to the first column of the next month.
    }
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述