如何在Winform的DataGridView中对数据组进行格式化?

本文关键字:数据 格式化 Winform DataGridView | 更新日期: 2023-09-27 18:19:11

在我的Winforms 4.5应用程序中,我将一个DataGridView绑定到一个名为Products的SQL Server Db表。该表有一个名为Category的列,显示产品所属的类别。例如:

C1  P11
C1  P112
C2  P21
C2  P22
C2  P23
C3  P31
..  ...
C4  P41
C4  P42
..  ...

我想设置基于每个组的DataGridView的交替行样式(不是每一行)。因此,在上面的示例中,前两行(C1组)将具有默认背景色,接下来的三行(C2组)将具有深灰色背景色,C3组的行将具有默认背景色,C4组的行将具有深灰色背景色,以此类推。我怎样才能做到这一点呢?请注意,每组中的行数将根据用户输入的数据动态变化;上面显示的演示数据并不是真实数据。

我尝试了以下两篇MSDN文章的示例,但它们不完全是我上面想要的:

  1. 为Windows窗体DataGridView控件设置交替行样式
  2. 自定义Windows窗体数据视图控件中的数据格式

编辑在真实的数据中,类别前面不会包含数字。分类的真实例子可以是:水果,蔬菜,乳制品,…

如何在Winform的DataGridView中对数据组进行格式化?

既然你知道每个类别,你可以事先为每一组定义一个颜色。否则,您需要为总数未知的组制作颜色生成器。这里有一个方法:

    public static void Categorize(DataGridView dgv)
    {
        // Set colors for each category
        Color apples = Color.Red,
              bananas = Color.Yellow,
              oranges = Color.Orange;
        // Loop the rows
        foreach (DataGridViewRow row in dgv.Rows)
        {
            // Read category
            string category = row.Cells["GroupColumn"].Value.ToString();
            // Set color according to category
            switch (category)
            {
                case "Apple": row.DefaultCellStyle.BackColor = apples; return;
                case "Banana": row.DefaultCellStyle.BackColor = bananas; return;
                // If the group wasn't listed, skip
                default: return;
            }
        }
    }

不确定这将是实现您所追求的最高效的方式,但我可能会尝试根据您在这里定义的逻辑(本质上是基于组值)手动设置每行的背景颜色。它看起来像这样:

首先设置一些模拟数据:

public class DAL
{
    public static DataTable GetMockData()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("ProductId", Type.GetType("System.Int32"));
        dt.Columns.Add("ProductName", Type.GetType("System.String"));
        dt.Columns.Add("ProductCategory", Type.GetType("System.String"));
        dt.Rows.Add(new object[] { 1, "Apple", "Fruit" });
        dt.Rows.Add(new object[] { 2, "Banana", "Fruit" });
        dt.Rows.Add(new object[] { 3, "Pear", "Fruit" });
        dt.Rows.Add(new object[] { 4, "Potato", "Vegetable" });
        dt.Rows.Add(new object[] { 5, "Celery", "Vegetable" });
        dt.Rows.Add(new object[] { 6, "Carrot", "Vegetable" });
        dt.Rows.Add(new object[] { 7, "Hominy", "Vegetable" });
        dt.Rows.Add(new object[] { 8, "Wine", "Beverage" });
        dt.AcceptChanges();
        return dt;
    }
}

显示将使用此数据的表单,并根据ProductCategory替换行背景颜色:

public Form1()
{
    InitializeComponent();
    DataTable dt = DAL.GetMockData();
    this.dataGridView1.DataSource = dt;
}
private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
    Dictionary<string, int> categoryNumber = GetUniqueCategories(sender as DataGridView);
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if (row.Cells["ProductCategory"].Value != null)
            row.DefaultCellStyle.BackColor = GetRowColor(categoryNumber[row.Cells["ProductCategory"].Value.ToString()]);
    }
}
private Color GetRowColor(int categoryNumber)
{
    if (categoryNumber % 2 == 0)
        return Color.White; //default row color
    else
        return Color.LightGray; //alternate row color
}
private Dictionary<string, int> GetUniqueCategories(DataGridView dt)
{
    int i = 0;
    Dictionary<string, int> categoryNumber = new Dictionary<string, int>();
    foreach (DataGridViewRow row in dt.Rows)
    {
        if (row.Cells["ProductCategory"].Value != null)
        {
            if (!categoryNumber.ContainsKey(row.Cells["ProductCategory"].Value.ToString()))
            {
                categoryNumber.Add(row.Cells["ProductCategory"].Value.ToString(), i);
                i++;
            }
        }
    }
    return categoryNumber;
}