简体   繁体   English

更改单元格的背景色在Form的构造函数中不起作用

[英]Changing the BackColor of a Cell Does't work in Form's Constructor

My code seems pretty straight forward, I'm not sure what I'm missing... 我的代码似乎很简单,我不确定我缺少什么...

I'm looping through each row in dataGridView.Rows , then looping through each cell and checking if its value is "OK" then I change the cell color to Color.Red and also write "IF WAS TRUE" in console. 我遍历dataGridView.Rows每一行,然后遍历每个单元格并检查其值是否为"OK"然后将单元格颜色更改为Color.Red并在控制台中也写了"IF WAS TRUE"

I have that nice little "IF WAS TRUE" in console window just to prove to myself that the if statement is getting caught (it is). 我在控制台窗口中有一个很好的小"IF WAS TRUE" ,向我自己证明了if语句已被捕获(是)。 But my cell color remains unchanged White . 但我的单元格颜色保持不变White

Any advice would be appreciated! 任何意见,将不胜感激!

public partial class Form1 : Form
{
    public static BindingList<Record> record_list = new BindingList<Record> { };
    public static DataGridViewCellStyle style = new DataGridViewCellStyle();
    public Form1()
    {
        InitializeComponent();
        FillData();
        foreach (DataGridViewRow row in dataGridView.Rows)
        {
            for (var i = 0; i < row.Cells.Count; i++)
            {
                Console.WriteLine(row.Cells[i].Value);
                if (row.Cells[i].Value as string == "OK")
                {
                    row.Cells[i].Style.BackColor = Color.Red;
                    Console.WriteLine("IF WAS TRUE");
                }
            }
        }
    }
    void FillData()
    {
        record_list.Add(new Record("Support-19", "TEST", 0, 0.0, "", 
            "LOC CODE2", 0.0, 0, 0, 0.0, ""));
        record_list.Add(new Record("Support-99", "ROBOTS", 0, 0.0, "",
            "OK", 0.0, 0, 0, 0.0, ""));
        record_list.Add(new Record("Support-27", "TEST2", 0, 0.0, "", 
            "LOC CODE1", 0.0, 0, 0, 0.0, ""));
        dataGridView.DataSource = record_list;
    }
}
public class Record
{
    public string Station { get; set; }
    public string UserName { get; set; }
    public int EvtActive { get; set; }
    public double EvtTime { get; set; }
    public string EvtTimeString { get; set; }
    public string LocCode { get; set; }
    public double LastLoop { get; set; }
    public int CompLvl { get; set; }
    public int RecordID { get; set; }
    public double ConnectTime { get; set; }
    public string Notes { get; set; }

    public Record(string a, string b, int c, double d, string e,
        string f, double g, int h, int i, double j, string k)
    {
        this.Station = a;
        this.UserName = b;
        this.EvtActive = c;
        this.EvtTime = d;
        this.EvtTimeString = e;
        this.LocCode = f;
        this.LastLoop = g;
        this.CompLvl = h;
        this.RecordID = i;
        this.ConnectTime = j;
        this.Notes = k;
    }
}

EDIT: This was marked as duplicate, but this seems different to me. 编辑:这被标记为重复,但这对我来说似乎有所不同。 In the other SO post, it looks like a cell is being sent to a function directly where as I am iterating over cells. 在另一篇SO帖子中,看起来像是将单元格直接发送到函数中,因为我正在遍历单元格。 I try to call the BackColor property in a similar manner and I get no results... 我尝试以类似方式调用BackColor属性,但未得到任何结果。

The changes which you make on cells and rows of DataGridView in constructor (before form Load event) will not be persisted and they will be lost. 您对构造函数中的DataGridView单元格和行所做的更改(在表单Load事件之前)将不会保留,并且将丢失。 It's not about just styles, it's about all changes on rows and cells. 这不仅仅是样式,还涉及行和单元格上的所有更改。

In fact the columns and rows which you see after load are not those that you see in constructor. 实际上,加载后看到的列和行不是在构造函数中看到的列和行。

The short answer (as said) is you should initialize styles in Load event of form. 简短的答案(如前所述)是您应该在表单的Load事件中初始化样式。 But Why? 但为什么?

Why do changes which you make on cells and rows of DataGridView in constructor don't persist and they lost? 为什么在构造函数中对DataGridView单元格和行所做的更改不持久并且丢失?

The answer is because of OnBindingContextChanged of DataGridView . 答案是因为有DataGridViewOnBindingContextChanged

When you show a Form sequence of tasks that shows a Form cause calling these methods: CreateControlOnBindingContextChanged . 当你展示一个Form的任务序列,显示了Form原因调用这些方法: CreateControlOnBindingContextChanged Which cause OnParentBindingContextChanged of each child control be called and as a result, OnBindingContextChanged of all child controls will be called. 这导致每个子控件的OnParentBindingContextChanged被调用,结果,所有子控件的OnBindingContextChanged将被调用。

Now if you take a look at DataGridView.OnBindingContextChanged you will see, a method named RefreshColumnsAndRows called which clears all rows and columns and add them again: 现在,如果您看一下DataGridView.OnBindingContextChanged ,将看到一个名为RefreshColumnsAndRows的方法,该方法将清除所有行和列并再次添加它们:

private void RefreshColumnsAndRows()
{
    this.Rows.ClearInternal(false /*recreateNewRow*/);
    RefreshColumns();
    RefreshRows(true /*scrollIntoView*/);
}

So the columns and rows which you see after load are not those that you see in constructor. 因此,加载后看到的列和行不是在构造函数中看到的列和行。 They are new objects. 它们是新对象。 So changes which you made on rows and columns in constructor will not be persisted. 因此,您对构造函数中的行和列所做的更改将不会保留。

What's the correct way of dynamically changing styles? 动态更改样式的正确方法是什么?

Although you can move your code to Load event of Form but a more suitable place to style rows and cells dynamically is using CellFormatting event of DtaGridView 虽然你可以将你的代码Load的事件Form ,但一个更合适的地方的风格行和单元格动态使用CellFormatting的事件DtaGridView

Decorating the cells doesn't "stick" when you try to run your code in the form's constructor. 当您尝试在窗体的构造函数中运行代码时,装饰单元格不会“粘住”。 Move it to the form's OnLoad override instead: 将其移动到表单的OnLoad替代中:

protected override void OnLoad(EventArgs e) {
  base.OnLoad(e);

  foreach (DataGridViewRow row in dataGridView.Rows)
  {
    for (var i = 0; i < row.Cells.Count; i++)
    {
      Console.WriteLine(row.Cells[i].Value);
      if (row.Cells[i].Value as string == "OK")
      {
        row.Cells[i].Style.BackColor = Color.Red;
        Console.WriteLine("IF WAS TRUE");
      }
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM