Как изменить стиль ячейки DataGridView, когда пользователь редактирует ячейку - PullRequest
0 голосов
/ 17 апреля 2020

Мне нужно изменить задний цвет ячейки DataGridView на основе определенных условий, так как пользователь редактирует ячейку. Прямо сейчас я могу изменить BackColor только после того, как ячейка потеряет фокус.

В частности, пока пользователь печатает в ячейке, мне нужно проверить DataTable, с которым DataGridView связан с сравните то, что пользователь печатает, с тем, какое значение находится в DataTable в соответствующей ячейке. Если он другой, мне нужно поменять BackColor на Желтый. И если пользователь изменяет значение в ячейке обратно на исходное значение в DataTable, мне нужно удалить цвет.

Я попытался возиться с событием KeyPress, но не могу понять как получить указанный c индекс строки / столбца редактируемой ячейки, чтобы я мог правильно проверить его значение по отношению к соответствующему DataTable значению индекса строки / столбца.

1 Ответ

0 голосов
/ 21 апреля 2020

Это нелегко, вам нужно разобраться с несколькими вещами:

  • Элемент управления для редактирования ячейки отличается от элемента управления, поэтому, когда редактирование начинается, найдите элемент управления для редактирования и установите начальный цвет для это путем сравнения текста со значением источника данных.
  • Когда элементы управления редактированием будут отображаться, обработайте его событие TextChanged, а в обработчике события TextChanged сравните текст со значением источника данных и раскрасьте текстовое поле. основанный на этом.
  • Когда вы закончите sh редактирование, значение не будет pu sh для источника данных, пока вы не оставите запись или не завершите редактирование явным образом, поэтому, когда редактирование заканчивается, pu * Значение 1030 * для источника данных.
  • Обрабатывать рисование ячейки и раскрашивать ячейку.
  • Использовать другой цвет для новых строк (если хотите). Они отличаются от измененных строк, у них нет оригинальной версии.
  • Поскольку мы обработали рисование ячеек, если значения в источнике данных изменятся, ячейка будет перекрашена.

Вот снимок экрана:

enter image description here

Вот рабочий пример:

public DataTable GetProducts()
{
    var products = new DataTable();
    products.Columns.Add("Id", typeof(int));
    products.Columns.Add("Name", typeof(string));
    products.Columns.Add("Price", typeof(int));
    products.Rows.Add(1, "Product 1", 100);
    products.Rows.Add(2, "Product 2", 200);
    products.AcceptChanges();
    return products;
}
private void Form1_Load(object sender, EventArgs e)
{
    dataGridView1.AutoGenerateColumns = true;
    dataGridView1.DataSource = GetProducts();
    dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
    dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
    dataGridView1.CellPainting += dataGridView1_CellPainting;
    dataGridView1.CellBeginEdit += dataGridView1_CellBeginEdit;
    dataGridView1.CellEndEdit += dataGridView1_CellEndEdit;
}
private void dataGridView1_CellEndEdit(object sender,
    DataGridViewCellEventArgs e)
{
    if (e.ColumnIndex < 0 || e.RowIndex < 0 || e.RowIndex == dataGridView1.NewRowIndex)
        return;
    var drv = dataGridView1.Rows[e.RowIndex].DataBoundItem as DataRowView;
    if (drv != null)
    {
        drv.EndEdit();
    }
}
private void dataGridView1_CellBeginEdit(object sender, 
    DataGridViewCellCancelEventArgs e)
{
    if (e.ColumnIndex < 0 || e.RowIndex < 0 || e.RowIndex == dataGridView1.NewRowIndex)
        return;
    BeginInvoke(new Action(() =>
    {
        var textBox = dataGridView1.EditingControl as DataGridViewTextBoxEditingControl;
        if (textBox != null)
        {
            SetEditingControlColor(textBox);
        }
    }));
}
private void dataGridView1_CellPainting(object sender, 
    DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex < 0 || e.RowIndex < 0 || e.RowIndex == dataGridView1.NewRowIndex)
        return;
    var drv = dataGridView1.Rows[e.RowIndex].DataBoundItem as DataRowView;
    if (drv != null && drv.Row.HasVersion(DataRowVersion.Original))
    {
        var column = dataGridView1.Columns[e.ColumnIndex].DataPropertyName;
        if (drv.Row[column, DataRowVersion.Current]
            .Equals(drv.Row[column, DataRowVersion.Original]))
        {
            e.CellStyle.BackColor = Color.White;
        }
        else
        {
            e.CellStyle.BackColor = Color.Yellow;
        }
        return;
    }
    e.CellStyle.BackColor = Color.LimeGreen;
}
void dataGridView1_EditingControlShowing(object sender,
    DataGridViewEditingControlShowingEventArgs e)
{
    var textBox = e.Control as DataGridViewTextBoxEditingControl;
    if (textBox != null)
    {
        textBox.TextChanged -= textbox_TextChanged;
        textBox.TextChanged += textbox_TextChanged;
    }
}
private void textbox_TextChanged(object sender, EventArgs e)
{
    var textBox = (DataGridViewTextBoxEditingControl)sender;
    SetEditingControlColor(textBox);
}
void SetEditingControlColor(DataGridViewTextBoxEditingControl textBox)
{
    var dgv = textBox.EditingControlDataGridView;
    var drv = dgv.CurrentCell.OwningRow.DataBoundItem as DataRowView;
    if (drv != null && drv.Row.HasVersion(DataRowVersion.Original))
    {
        var column = dgv.Columns[dgv.CurrentCell.ColumnIndex].DataPropertyName;
        var value = drv.Row[column, DataRowVersion.Original];
        if (textBox.Text.Equals($"{value}"))
        {
            textBox.BackColor = Color.White;
            textBox.Parent.BackColor = Color.White;
        }
        else
        {
            textBox.BackColor = Color.Yellow;
            textBox.Parent.BackColor = Color.Yellow;
        }
        return;
    }
    textBox.BackColor = Color.LimeGreen;
    textBox.Parent.BackColor = Color.LimeGreen;
}
...