如何根据行背景色对datagridview进行排序?

时间:2019-06-10 05:25:39

标签: c# winforms datagridview

我在WinForms(c#)项目中有一个DataGridView。如果满足特定条件,则将格式化其行。这是代码:

private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    foreach (DataGridViewRow Myrow in dataGridView1.Rows)
    {
        string BEFORE_HYPHEN = GetUntilOrEmpty(Convert.ToString(Myrow.Cells[2].Value));
        if (BEFORE_HYPHEN.Length == 2)
        {
        }
        else
        {
            Myrow.DefaultCellStyle.BackColor = Color.Yellow;
            Myrow.DefaultCellStyle.ForeColor = Color.Black;
        }
    }
}

现在,我要做的是首先显示带有黄色BackColor的行(根据行背景色排序)。

2 个答案:

答案 0 :(得分:3)

有颜色的问题

您没有有效地使用CellFormatting事件。您会看到,此事件正在为网格的每个单元格调用。您应该检查一个特定的单元格并为其分配自定义格式。通过实施,您将重新计算每个单元格的整个网格。

这是无效的,但更重要的是,这种方法将使按底色对网格进行排序变得更加困难。格式化通常是显示数据网格的最后一步。您需要以某种方式检测事件何时在网格的每个单元中运行,然后继续对其进行排序。

您可能应该只运行一次着色循环,而不是使用CellFormatting。如果网格是数据绑定的,则可以在DataBindingComplete中进行操作;如果不是,则可以在初始化之后进行。

排序databoud DataGridView

如果datagridview是数据绑定的,则应该对基础数据源而不是网格本身进行排序。也许,您需要预先计算每一行的颜色,对容器进行排序,然后再绑定DataGridView。

有关实施思路,请参见以下问题:

更新:当您将网格绑定到数据表时,我们可以使用@TaWCustom sorting order - DataGridView中发布的代码作为起点。

这是一个简单的例子:

//we'll need to process this table
var table = DATASET_DATA.Tables[0];

//First, add a column for BackColor and calculate values
//Here I use a simple column of type Color and default order (alphabetically, by color name)
//If you need a more complicated sorting, consider creating a numeric (BackColorOrder) column instead
table.Columns.Add("BackColor", typeof(Color));
foreach (DataRow row in table.Rows)
{
    string BEFORE_HYPHEN = GetUntilOrEmpty(Convert.ToString(row[2]));
    if (BEFORE_HYPHEN.Length == 2)
    {
        //white, or whatever your default color is
        row["BackColor"] = Color.White;
    }
    else
    {
        row["BackColor"] = Color.Yellow;
    }
}

//Assign a sorted binding source as a datasource
var bs = new BindingSource
{
    DataSource = table,
    Sort = "BackColor ASC"
};
dataGridView1.DataSource = bs;
//Hide backcolor from the grid
//If this column has a meaning in your application (some kind of a status?)
//Consider displaying it, so the user will be able to change sort order
dataGridView1.Columns["BackColor"].Visible = false;

...

/// <summary>
/// We're using DataBindingComplete to calculate color for all rows
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
     //Assign a pre-calculated BackColor for grid rows
     foreach (DataGridViewRow row in dataGridView1.Rows)
     {
          row.DefaultCellStyle.BackColor = (Color)row.Cells["BackColor"].Value;
     }
}

这里是full, runnable example。结果看起来像这样:

enter image description here

排序非数据绑定的DataGridView

如果您的datagridview是 not 数据绑定的,则应该可以使用Sort(IComparer comparer)对其进行排序:

dataGridView1.Sort(new BackColorComparer());

...
/// <summary>
/// Custom comparer will sort rows by backcolor
/// </summary>
private class BackColorComparer : System.Collections.IComparer
{
     public int Compare(object x, object y)
     {
          var row1 = (DataGridViewRow)x;
          var row2 = (DataGridViewRow)y;
          //Sorting by color names, replace with custom logic, if necessary
          return string.Compare(
               row1.DefaultCellStyle.BackColor.ToString(),
               row2.DefaultCellStyle.BackColor.ToString());
     }
}

确保仅在为所有行计算完BackColor后才运行此代码。

答案 1 :(得分:1)

您需要按以下方式更改datagridview数据源:

var sorted = DATASET_DATA.Tables[0].Select().OrderBy(row =>
{
    string BEFORE_HYPHEN = GetUntilOrEmpty(Convert.ToString(row.ItemArray[2]));
    return BEFORE_HYPHEN.Length == 2;
});
dataGridView1.DataSource = sorted.CopyToDataTable();