Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

c# - 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.

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). But my cell color remains unchanged 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. I try to call the BackColor property in a similar manner and I get no results...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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. 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. But Why?

Why do changes which you make on cells and rows of DataGridView in constructor don't persist and they lost?

The answer is because of OnBindingContextChangedof DataGridView.

When you show a Form sequence of tasks that shows a Form cause calling these methods: CreateControlOnBindingContextChanged. Which cause OnParentBindingContextChanged of each child control be called and as a result, OnBindingContextChanged of all child controls will be called.

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:

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...