【问题标题】:Cell Formatting In DataGridView On DataBindingCompleteDataBindingComplete 上的 DataGridView 中的单元格格式
【发布时间】:2014-08-07 21:58:09
【问题描述】:

我在工作中的一个项目的要求方面遇到问题。我正在做的是将数据表绑定到 DataGridView(DGV) 的数据源。然后,我遍历 DataGridView 并检查单元格的值是否为 1 * 或 2 **,并使用工具提示和红色背景格式化这些单元格。如果我使用按钮事件来触发这一切都很好。但是,如果我希望在使用 DataBindingComplete 事件加载表单时自动发生这种情况,则它无法正常工作。问题是 DataBindingComplete 多次触发。我读了this SO question,它给了我几个尝试的选择,但没有一个奏效。代码如下:

public partial class TestForm2 : Form
{
    private DataTable dt;
    private int methodCalls = 0;
    private bool isFormatted = false;

    public TestForm2()
    {
        InitializeComponent();
        buildDataTable();
        dataGridView1.DataBindingComplete += dataGridView1_DataBindingComplete;
    }

    private void TestForm2_Load(object sender, EventArgs e)
    {
        bindData();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        formatDataGridView();
    }

    private void bindData()
    {
        dataGridView1.DataSource = dt;
    }

    private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        //If this code is commented out the program will work just fine 
        //by just clicking the button

        //This was added to prevent formatDataGridView from executing more
        //than once.  Even though I unreg and rereg the event handler, the 
        //method was still being called 3 - 4 times. This successfully
        //prevented that but only the *'s were removed and no red back color
        //added to the cells.
        if(!isFormatted)
        {
            formatDataGridView();
        }
    }

    private void buildDataTable()
    {
        dt = new DataTable();

        dt.Columns.Add("col1");
        dt.Columns.Add("col2");
        dt.Columns.Add("col3");
        dt.Columns.Add("col4");
        Random randNum = new Random();
        for(int i = 0; i < 10; i++)
        {
            DataRow dr;
            object[] rowItems = new object[dt.Columns.Count];

            for(int j = 0; j < dt.Columns.Count; j++)
            {
                int number = randNum.Next(1, 20);

                if(number % 7 == 0)
                {
                    rowItems[j] = number + "*";
                }
                else if(number % 5 == 0)
                {
                    rowItems[j] = number + "**";
                }
                else
                {
                    rowItems[j] = number;
                }
            }

            dr = dt.NewRow();
            dr.ItemArray = rowItems;
            dt.Rows.Add(dr);
        }
    }

    private void formatDataGridView()
    {
        // I noticed that I needed to unregister the event handler to 
        // prevent DataBindingComplete from firing during the format
        dataGridView1.DataBindingComplete -= dataGridView1_DataBindingComplete;
        foreach(DataGridViewRow row in dataGridView1.Rows)
        {
            string originalCell;
            string reformattedCell;

            if(row.Cells["col1"].Value != null)
            {
                originalCell = row.Cells["col1"].Value.ToString();

                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    row.Cells["col1"].Value = reformattedCell;
                    row.Cells["col1"].Style.BackColor = Color.Red;
                    row.Cells["col1"].ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    row.Cells["col1"].Value = reformattedCell;
                    row.Cells["col1"].Style.BackColor = Color.Red;
                    row.Cells["col1"].ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }
            }

            if (row.Cells["col2"].Value != null)
            {
                originalCell = row.Cells["col2"].Value.ToString();

                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    row.Cells["col2"].Value = reformattedCell;
                    row.Cells["col2"].Style.BackColor = Color.Red;
                    row.Cells["col2"].ToolTipText = "Divisible by 5";
                }

                if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    row.Cells["col2"].Value = reformattedCell;
                    row.Cells["col2"].Style.BackColor = Color.Red;
                    row.Cells["col2"].ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }
            }

            if (row.Cells["col3"].Value != null)
            {
                originalCell = row.Cells["col3"].Value.ToString();

                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    row.Cells["col3"].Value = reformattedCell;
                    row.Cells["col3"].Style.BackColor = Color.Red;
                    row.Cells["col3"].ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    row.Cells["col3"].Value = reformattedCell;
                    row.Cells["col3"].Style.BackColor = Color.Red;
                    row.Cells["col3"].ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }
            }

            if (row.Cells["col4"].Value != null)
            {
                originalCell = row.Cells["col4"].Value.ToString();

                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    row.Cells["col4"].Value = reformattedCell;
                    row.Cells["col4"].Style.BackColor = Color.Red;
                    row.Cells["col4"].ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    row.Cells["col4"].Value = reformattedCell;
                    row.Cells["col4"].Style.BackColor = Color.Red;
                    row.Cells["col4"].ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }
            }
        }
        // Reregistering the event handler
        dataGridView1.DataBindingComplete += dataGridView1_DataBindingComplete;
        isFormatted = true;
        methodCalls++;
        MessageBox.Show("Method Calls: " + methodCalls);
    }
}

我不确定如何解决这个问题,但必须有办法。直到最近我才对 DataBindingComplete 不熟悉,所以我肯定会在这里学到一些东西。感谢大家的帮助,帮助我学习新东西!

【问题讨论】:

  • 尝试使用 CellFormatting 事件。
  • 我认为出错的是,在 DataBindEvent 期间,您正在更改网格中的一些值。然后将这些更改保存在 DataSource 中,之后 DataSource 再次与新值绑定,重新触发 DataBindEvent。
  • @BartvanderDrift 我相信是这样。如果我没有通过在我的 formatDataGridView 方法中声明 dataGridView1.DataBindingComplete -= dataGridView1_DataBindingComplete 来取消注册 dataGridView1_DataBindingComplete 事件处理程序,则计数器 methodCalls 报告该方法被调用的次数与所做更改的次数一样多。但是,我通过取消注册事件处理程序来阻止这种情况的发生,以防止这些更改触发事件。我还放了一个 bool isFormatted,一旦调用该方法就会设置为 true,条件 if(!isFormatted) 也可以防止这种情况发生
  • 所以尽管从事件中解除绑定,但 dataGridView1_DataBindingComplete 函数被多次调用?
  • @LarsTech 我可能有一个使用您的方法的解决方案。我只需要重写一些东西来测试它。感谢您的意见!

标签: c# data-binding datagridview event-handling


【解决方案1】:

CellFormatting 事件处理程序是我最终解决问题的途径。

    private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        string originalCell;
        string reformattedCell;

        if (this.dataGridView1.Columns[e.ColumnIndex].Name == "col1")
        {
            if(e.Value != null)
            {
                DataGridViewCell cell = 
                    this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
                originalCell = e.Value.ToString();
                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }

            }

        }

        if (this.dataGridView1.Columns[e.ColumnIndex].Name == "col2")
        {
            if (e.Value != null)
            {
                DataGridViewCell cell =
                    this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
                originalCell = e.Value.ToString();
                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }

            }

        }

        if (this.dataGridView1.Columns[e.ColumnIndex].Name == "col3")
        {
            if (e.Value != null)
            {
                DataGridViewCell cell =
                    this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
                originalCell = e.Value.ToString();
                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }

            }

        }

        if (this.dataGridView1.Columns[e.ColumnIndex].Name == "col4")
        {
            if (e.Value != null)
            {
                DataGridViewCell cell =
                    this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
                originalCell = e.Value.ToString();
                if (originalCell.Count(c => c == '*') == 2)
                {
                    reformattedCell = originalCell.Replace("**", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 5";
                }

                else if (originalCell.Count(c => c == '*') == 1)
                {
                    reformattedCell = originalCell.Replace("*", "");

                    cell.Value = reformattedCell;
                    cell.Style.BackColor = Color.Red;
                    cell.ToolTipText = "Divisible by 7";
                }

                else
                {
                    //do nothing
                }

            }

        }
    }

【讨论】:

  • 很高兴它成功了。不要忘记将您自己的答案标记为正确的答案:-)
【解决方案2】:

你需要改变:

  • DataBindingComplete 事件中的格式,但不是值
  • 提供一个“干净”的值以在 CellFormatting 事件 (e.Value) 中显示,它不会更改存储在 dataviewgrid 单元格中的基础值,只是传递给绘画事件以在屏幕上显示的值

请记住,在通过数据设置格式时,如果 CellStyles 的类型有限,例如 Good Result、Bad Result(我的代码实际上有大约 11 种默认样式),为了提高效率,首先创建样式。

然后在检查单元格值并确定要使用的样式时分配它们。

唯一需要注意的是,稍后如果您以某种方式更改 Column = 12、Row = 4 单元格样式,它将影响“共享”相同默认 DataGridViewCellstyle 的所有单元格。

例如

            Font bFont = new Font("Calibri", defFontSize, FontStyle.Bold);       // Bold font
            Font iFont = new Font("Calibri", defFontSize, FontStyle.Italic);     // Italic font
            Font nFont = new Font("Calibri", defFontSize);                       // Normal font

            DataGridViewCellStyle dgvcsOKRESULT = new DataGridViewCellStyle()
            {
                Font = nFont,
                ForeColor = Color.White,
                BackColor = Color.Green,
            };

            DataGridViewCellStyle dgvcsBADRESULT = new DataGridViewCellStyle()
            {
                Font = bFont,
                ForeColor = Color.White,
                BackColor = Color.Red,
            };

【讨论】:

  • 是的,这将使代码更具可读性!感谢您的建议,我将来一定会使用它...赞成!
  • 为了获得更多来之不易的建议(刚刚完成代码!),我最终将显示值存储在 Cells.Tag 属性中作为字符串对象。这意味着实际的 CellFormating 事件代码只有一行:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>> e.Value = this.dataGridViewControl.Rows[e.RowIndex].Cells[e.ColumnIndex].Tag;
【解决方案3】:

从 bindData 方法调用 formatDataGridView 并忘记 DataBinding 事件:

private void bindData()
{
  dataGridView1.DataSource = dt;
  formatDataGridView();
}

或者这是不可能的原因?

【讨论】:

  • 信不信由你,这是我试图开始的。我一直遇到提示和背景颜色缺失的问题,而且我在阻止 CellValueChanged 事件触发时遇到了问题。我的逻辑是我的 DGV 在我尝试格式化之前没有完成数据绑定。这就是为什么我尝试使用 DataBindingComplete 事件处理程序来确保数据绑定在我尝试格式化 DGV 之前完成。但是哦,好吧,我想我已经决定使用 CellFormatting 事件是要走的路。它似乎可以按我的意愿工作。我将发布我的解决方案。感谢您的帮助!
  • 顺便说一句,对于我在这个 SO 问题中使用的示例,您的答案在技术上确实有效;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多