Answered IF Else statement on background colour of label.

Ivolution93

New member
Joined
Oct 28, 2020
Messages
4
Programming Experience
Beginner
Hello,

Can anybody give me any guidance on how to create an if else statement on a background colour of a label.
For example, if the background colour of a label is white then do this else do this.
 
Solution
You would do something like this, but not quite this because this is bad code :
C#:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            ControlAction action = new ControlAction();
            Task colorChange_Task = new Task(() => action.LabelBG_ColorChange(label1, Color.Red)); colorChange_Task.Start();
        }

        private void label1_BackColorChanged(object sender, EventArgs e)
        {
            Debug.Write("Color was changed");
        }
    }
    public class ControlAction
    {
        public Color LabelBG_ColorChange(Control cnl, Color clr)
        {...
Why are you using for UI as your data model? Modern programming practices highly recommend separating your view, data model, and business logic from each other giving rise to the MVC, MVP, and MVVM design patterns.

Anyway if you want to persist with this terrible idea, just check the background color property. Most WinForms controls have this property exposed.
 
You would do something like this, but not quite this because this is bad code :
C#:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button2_Click(object sender, EventArgs e)
        {
            ControlAction action = new ControlAction();
            Task colorChange_Task = new Task(() => action.LabelBG_ColorChange(label1, Color.Red)); colorChange_Task.Start();
        }

        private void label1_BackColorChanged(object sender, EventArgs e)
        {
            Debug.Write("Color was changed");
        }
    }
    public class ControlAction
    {
        public Color LabelBG_ColorChange(Control cnl, Color clr)
        {
            if (cnl.BackColor == Color.Transparent)
                Debug.WriteLine("I am Transparant");
            else
                cnl.BackColor = clr;
            return clr;
        }
    }
In the else section. If you where to access the text property of that control, cnl.Text you would be met with an exception of type :
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on.'
By passing the control into the new task, you are able to update the color of the label at ease, and while this works, but it's not technically correct. Let me show you an example and explain about how you should access controls from another thread. If you don't use the control you passed into LabelBG_ColorChange, you would be forced to do it like this :
C#:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }
        private void button2_Click(object sender, EventArgs e)
        {
            ControlAction action = new ControlAction();
            Task colorChange_Task = new Task(() => action.Color = action.LabelBG_ColorChange(label1, Color.Red)); colorChange_Task.Start();
            Debug.WriteLine($"Your color is : { action.Color }");
        }

        private void label1_BackColorChanged(object sender, EventArgs e)
        {
            Debug.Write(string.Concat("Color was changed", Environment.NewLine));
        }
    }
    public class ControlAction
    {
        public Color Color { get; set; } = Color.Transparent;
        public Color LabelBG_ColorChange(Control ctl, Color clr)
        {
            if (ctl.BackColor == Color.Black)
                Debug.WriteLine("I am already Black");
            else if (ctl.BackColor != clr)
            {
                Form.ActiveForm.Controls.Find("label1", false)[0].Invoke(new Delegate_Callback_To(UpdateUI_With_NewItem), clr, ctl);
                Color = clr;
            }
            return clr;
        }
        public delegate void Delegate_Callback_To(Color ctl_Color, Control control);

        public void UpdateUI_With_NewItem(Color ctl_Color, Control control)
        {
            control.BackColor = ctl_Color;
        }
    }
Notice on line 29, we are forced to search the active form for the control using the find method because we are not using the control we originally passed in to this method. And assuming the control is not null, (I should have added some null checks there ?) and we invoke the control we want to update if its found. We do this because our calling method : button2_Click set the executed method to run on another thread, other than the UI thread where the control was created and belongs to. And so, if we don't invoke the control; we are accessing it incorrectly since it does not belong to the thread that is changing its properties. Line 29 above may also require your access modifier for your label be set to public.

Also note : Find("label1", false) assumes the control is on the main form and not on another container/control ie a panel or group box. And it will not search child controls while set to false. Changing false to true will allow the search pattern to find child controls for the name of the control you specified. This is worth noting if the control you want to find is a child control of another parent object.

Let me elaborate some more bad code which will cause the same error above.. This : Form.ActiveForm.Controls.Find("label1", false)[0].Text =""; is also bad code and that's because the control is being accessed illegally in the same manner as above. So a better way to write line 29 more appropriately would look like this :
C#:
ctl.Invoke(new Delegate_Callback_To(UpdateUI_With_NewItem), clr, ctl);
The same malpractice applies if we try to access the control we passed into the method with the following snipped : ctl.Text = ""; as this will also result in an illegal cross thread operation.

On a more advisable note to the above approach. This example I've demonstrated to you is fine to use in Winforms, since winforms is old and shitty, and this is how some developers used to write code for Winforms. They'd execute threads to carry out work, and from those threads, they would delegate back to their UI with any updates their threading method was required to carry back to the user interface. As pointed out above, it is bad practice to use your UI to carry out work or to use your UI as a model for anything other than an interactive interface for the end-user.

Since WPF was released, most modern developers use Model View Controllers, Model View Presentation, (These two are my favourite) or even the Model View View Model design. Windows forms is very old, and it's also EOL which means, you really shouldn't be using it, unless in some legacy type applications where you need meet a specific target. WPF is where it's at today, and Microsoft encourage users to use WPF over old and dated Winforms. And I would highly advise you to start learning WPF and all it has to offer, so that you can begin to learn modern day programming models and better programming practices. Doing so will allow you to build better, more stable and robust applications.

C#:
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

        }
        private void button2_Click(object sender, EventArgs e)
        {
            ControlAction action = new ControlAction();
            Task colorChange_Task = new Task(() => action.Color = action.LabelBG_ColorChange(label1, Color.Red)); colorChange_Task.Start();
            Debug.WriteLine($"Your color is : { action.Color }");
        }

        private void label1_BackColorChanged(object sender, EventArgs e)
        {
            Debug.Write(string.Concat("Color was changed", Environment.NewLine));
        }
    }
    public class ControlAction
    {
        public Color Color { get; set; } = Color.Transparent;
        public Color LabelBG_ColorChange(Control ctl, Color clr)
        {
            if (ctl.BackColor == Color.Black)
                Debug.WriteLine("I am already Black");
            else if (ctl.BackColor != clr)
            {
                ctl.Invoke(new Delegate_Callback_To(UpdateUI_With_NewItem), clr, ctl);
                Color = clr;
            }
            return clr;
        }
        public delegate void Delegate_Callback_To(Color ctl_Color, Control control);

        public void UpdateUI_With_NewItem(Color ctl_Color, Control control)
        {
            control.BackColor = ctl_Color;
        }
 
Solution
Back
Top Bottom