当用户在单元格中编辑和键入时更改 DataGridView 的单元格样式 [英] Change cell style of a DataGridView while the user is editing and typing in cell

查看:22
本文介绍了当用户在单元格中编辑和键入时更改 DataGridView 的单元格样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要根据特定条件更改 DataGridView 单元格的背景颜色,因为用户正在编辑该单元格.现在我只能在单元格失去焦点后更改 BackColor.

I need to change the back color of a DataGridView cell based on certain conditions, as the user is editing the cell. Right now I can only change the BackColor after the cell loses focus.

具体来说,当用户在单元格中键入时,我需要检查 DataGridView 绑定到的 DataTable 以比较用户键入的内容与什么值位于相应单元格的 DataTable 中.如果不同,我需要将 BackColor 更改为黄色.如果用户将单元格中的值更改回 DataTable 中的原始值,我需要删除颜色.

Specifically, while the user is typing in a cell, I need to check the DataTable that the DataGridView is bound to to compare what the user is typing to what value is in the DataTable in the corresponding cell. If it's different, I need to change the BackColor to Yellow. And if the user changes the value in the cell back to the original value in the DataTable, I need to remove the color.

我尝试处理 KeyPress 事件,但我不知道如何获取正在编辑的单元格的特定行/列索引,以便我可以根据相应的值正确检查它的值DataTable 的行/列索引值.

I tried messing around with the KeyPress event, but I can't figure out how to get the specific row/column index of the cell being edited so I can correctly check it's value against the corresponding DataTable's row/column index value.

推荐答案

这并不容易,你需要处理一些事情:

It's not easy, You need to handle a few things:

  • 单元格编辑控件与单元格不同,因此在开始编辑时,通过将文本与数据源值进行比较,找到编辑控件并为其设置初始颜色.
  • 当编辑控件要显示时,处理它的 TextChanged 事件,并在 TextChanged 事件处理程序中,将文本与数据源值进行比较,并根据该值为文本框着色.
  • 当你完成编辑时,值不会推送到数据源,直到你离开记录或明确调用结束编辑,所以当编辑结束时,将值推送到数据源.
  • 处理单元格绘画并为单元格着色.
  • 为新行使用不同的颜色(如果您愿意).它们与修改后的行不同,它们没有原始版本.
  • 由于我们已经处理了单元格绘制,如果数据源中的值发生变化,单元格将被重新绘制.
  • The cell editing control is different from the cell, so when edit is beginning, find the editing control and set the initial color for that by comparing the text with the datasource value.
  • When the editing controls is going to show, handle it's TextChanged event and in the TextChanged event handler, compare the text with the datasource value and colorize textbox based on that.
  • When you finish editing, the value will not push to data source, until after you leave the record or call end edit explicitly, so when edit is ending, push value to the data source.
  • Handle cell painting and colorize the cell.
  • Use a different color for new rows (if you like). They are different from modified rows, they don't have an original version.
  • Since we have handled cell painting, if the values in data source change, the cell will be repainted.

这是屏幕截图:

这是一个工作示例:

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

这篇关于当用户在单元格中编辑和键入时更改 DataGridView 的单元格样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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