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

时间:2017-01-27 09:52:47

标签: c# winforms datagridview merge

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

我想让Datagridview看起来像这样:

Datagridview example

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

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

此外,我不知道如何将日期值输入单元格/行标题

这就是我从一个月开始的日子

int year = DateTime.Now.Year;
int Jan = 1;
int daysInJan = System.DateTime.DaysInMonth(year, Jan);

1 个答案:

答案 0 :(得分:2)

linked solution适用于它提供的示例。那说:

  

我无法在标题

下获得超过2列

根据我们在评论中的讨论,我认为只需添加额外的列宽就可以在超过2列上拉伸“主”标题就足够了。这很好,直到我测试了足够的列以允许水平滚动。就在那时,我注意到一个月的“主要”标题仅在当月的1 st 日列显示时显示。

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

  1. 拉伸超过2列。
  2. 通过调整大小显示“主”标题,而不管1 st 列的可见性。
  3.   

    如何将日值输入单元格/行标题

  4. IDisposable对象的一般清理和重构。
  5. 在表单中,要设置网格,请执行以下操作:

    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;
    }
    

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

    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.
        }
    }
    

    enter image description here