Проблемы с окраской
Вы не используете событие CellFormatting
эффективно. Видите ли, это событие вызывается для каждой ячейки сетки. Вы должны проверить одну конкретную ячейку и назначить ей пользовательское форматирование. С вашей реализацией вы пересчитываете всю сетку для каждой ячейки.
Это неэффективно, но, что более важно, этот подход усложнит сортировку вашей сетки по заднему цвету. Форматирование обычно является последним этапом отображения сетки данных. Вам нужно как-то определить, когда событие запускается для каждой ячейки сетки, а затем приступить к его сортировке.
Вместо использования CellFormatting
вам, вероятно, следует запустить цикл раскраски только один раз. Вы можете сделать это в DataBindingComplete
, если ваша сетка привязана к базе данных, или сразу после инициализации, если это не так.
Сортировка базы данных DataGridView
Если ваше представление данных связано с данными, вы должны отсортировать основной источник данных, а не саму сетку. Возможно, вам придется предварительно рассчитать цвета для каждой строки, отсортировать контейнер и только после этого связать DataGridView.
См. Эти вопросы для идей реализации:
Обновление: поскольку вы привязываете сетку к датируемым данным, мы можем использовать код, опубликованный @ TaW в Настраиваемый порядок сортировки - 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;
}
}
Вот полный, работающий пример . Результат выглядит так:
![enter image description here](https://i.stack.imgur.com/Q0fHh.png)
Сортировка DataGridView без привязки к данным
Если ваше представление данных имеет не привязку к данным, вы сможете отсортировать его, используя 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
для всех строк.