Home > Net >  Winforms: Change background colour of an element depending on value of a variable
Winforms: Change background colour of an element depending on value of a variable

Time:06-14

I have a small project here in visual studio 2022, a Winforms c /CLR project. It is a pretty simple project and form, but I have an issue with the following:

In the Winforms app I use a small panel to display the status of some input that I get. I want to change the background colour of the panel depending on the status of that variable. So for example if the variable is 0, the background colour should be red, if the value of the variable is 1, it should be green.

I can easily make this work, when this is coupled to a trigger event from the user, such as mouseclick, mousehover, .... But how do I make this work dynamically during runtime, such that even while the variable changes during runtime, the backgroundcolour of the panel changes with it too, without the need of a user input event such as a mouseclick, ... ?

What kind of class need to be made in order to make this work?

CodePudding user response:

I suggest you to use the TextChanged event in the textbox, which triggers when the content of the textbox changes, you could refer to the following code:

private: System::Void textBox1_TextChanged(System::Object^ sender, System::EventArgs^ e) {

    if (textBox1->Text != "")
    {
        if (textBox1->Text == "1")
            button1->BackColor = Color::Red;
        else if (textBox1->Text == "2")
        {
            button1->BackColor = Color::Green;
        }

    }

}

The result is as follows:

enter image description here

CodePudding user response:

An example that shows how to bind the Property of a Control to the Property of managed class object, implementing the INotifyPropertyChanged interface, used to trigger value change notifications.

In the ColorTrigger class, when an the value of an int Property is changed, this also changes the value returned by a Property of Type Color and triggers a PropertyChanged notification.
This causes all Controls bound to the class object to read again the value of the Property specified in the binding:

somePanel->DataBindings->Add(
    "BackColor", trigger, "ColorValue", false, DataSourceUpdateMode::OnPropertyChanged
);

Here, DataBindings.Add() binds to the BackColor Property of a Panel Control to the ColorValue Property of the ColorTrigger class.

#pragma once
#include "ColorTrigger.h"

public ref class SomeForm : public System::Windows::Forms::Form
{
// Initialize with default values
private: ColorTrigger^ trigger = gcnew ColorTrigger();

public: SomeForm(void) { 
    InitializeComponent(); 
    somePanel->DataBindings->Add("BackColor", trigger, "ColorValue", false, DataSourceUpdateMode::OnPropertyChanged);
}

Or pass different Colors to the Constructor of the ColorTrigger class:

// [...]
private: ColorTrigger^ trigger;

public: SomeForm(void) { 
    InitializeComponent(); 
    trigger = gcnew ColorTrigger(gcnew array<Color> { 
        Color::Magenta, Color::Cyan, Color::Orange 
    });
    somePanel->DataBindings->Add("BackColor", trigger, "ColorValue", false, DataSourceUpdateMode::OnPropertyChanged);
}

Now, when you assign a new value to the Value Property of the ColorTrigger class, the Color returned by the ColorValue Property changes accordingly and a notification is sent, causing the Binding to update and with it the Property of Controls that share the binding.


ColorTrigger managed class:

Note that this line in the Property setter:

colorIdx = Math::Max(Math::Min(value, colors->Length - 1), 0);

trims the value in the range (0, [ColorArray].Length - 1).
You may want to throw instead, if value is outside the bounds of the array.

#pragma once
using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;

#define nameof(_propname) #_propname

public ref class ColorTrigger : INotifyPropertyChanged
{
public:
    virtual event PropertyChangedEventHandler^ PropertyChanged;

private:
    array<Color>^ colors;
    int colorIdx = 0;

public:
    ColorTrigger(void) {
        this->ColorTrigger::ColorTrigger(
            gcnew array<Color> {Color::Green, Color::Orange, Color::Red}
        );
    }
    ColorTrigger(array<Color>^ colorArr) {colors = colorArr;}

public : 
    property int Value {
        int get() { return colorIdx; }
        void set(int value) {
            if (value != colorIdx) {
                colorIdx = Math::Max(Math::Min(value, colors->Length - 1), 0);
                ColorValue = colors[colorIdx];
            }
        }
    }

    property Color ColorValue {
        Color get() { return colors[colorIdx]; }
        private : void set(Color value) {
            OnPropertyChanged(nameof(ColorValue));
        }
    }

    void OnPropertyChanged(String^ prop) {
        PropertyChanged(this, gcnew PropertyChangedEventArgs(prop));
    }
};
  • Related