合并多行行标题在DatagridView与C# [英] Merge mulitple row Headers in a DatagridView with C#

查看:307
本文介绍了合并多行行标题在DatagridView与C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



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

解决方案

链接解决方案适用于其提供的示例。说:


我无法在标题下获得超过2列




从我们在评论中的讨论中,我认为只需添加额外的列宽来扩展超过2列的主标题就足够了。这很好,直到我用足够的列测试以允许水平滚动。那时我发现一个月的主要标题只在该月份的1 st 日列显示时显示。



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


  1. 扩展2+列。

  2. 显示主要标题通过调整大小,而不管1 st 列的可见性。


  3. 如何获取日期值单元格/行标题



  4. 一般清理 IDisposable 对象和重构。 / li>






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

  private int [] daysInMonths; 

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

//为一年中的每一天添加一列;其中
//列名=日期(创建所有唯一的列名称)
//列标题文本=本月的数字日期
(int month = 1; month< = 12; month ++)
{
daysInMonths [month - 1] = DateTime.DaysInMonth(year,month);

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

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

//为(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;

//每个月,创建主标题的显示矩形并绘制。
foreach(int daysInMonth in daysInMonths)
{
Rectangle r1 = this.dataGridView1.GetCellDisplayRectangle(col,-1,true);

//从该月的第一个可见日开始矩形,
//,并为每个第二天添加列的宽度。
for(int day = 0; day< daysInMonth; day ++)
{
Rectangle r2 = this.dataGridView1.GetCellDisplayRectangle(col + day,-1,true);

if(r1.Width == 0)//单元格不显示。
{
r1 = r2;
}
else
{
r1.Width + = r2.Width;
}
}

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

使用(刷回=新的SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor))
使用(Brush fore = new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor))
使用(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; //移动到下个月的第一列。
}
}


I have a Project where I need to view data in Datagridview from a Database and it should look like a Gantt Chart.

I already tried a lot of code from the internet, but nothing worked properly

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

解决方案

The linked solution works fine for the example it provides. That said:

I wasn't able to get more than 2 columns under a title

From our discussion in comments, I thought it sufficient that you simply add additional column widths to stretch a "main" title over more than 2 columns. This was fine, until I tested with enough columns to permit horizontal scrolling. It was then that I noticed that the "main" title of a month was only displayed when the 1st day column of that month was visible.

The following code will address these issues:

  1. Stretching over 2+ columns.
  2. Displaying the "main" title through resizes and regardless of 1st column visibility.
  3. how to get the day values into the cells/row header

  4. General cleanup of IDisposable objects and refactoring.


In the Form, to set up the grid do the following:

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

Then add your event handlers:

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

这篇关于合并多行行标题在DatagridView与C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆