Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trigger event on value change C#

Tags:

c#

winforms

I'm trying to monitor a value and when it is changed, to update a text field after performing some calculations with a result.

The value I'm trying to monitor comes from an AGauge property (custom control). I want to update the text field when the AGauge.Value changes.

I've looked at questions such as This One but I don't really understand how this works, or what I need to change to get the result I'm looking for.

Can anyone better explain what I need to do in order for this to work?

The AGuage.Value is a float type, incase your wondering.

Thanks in advance.

Update 1

I have now added the following code to my project:

public class AGuage
{
    private float _value;

    public float Value
    {
        get
        {
            return this._value;
        }
        set
        {
            this._value = value;
            this.ValueChanged(this._value);
        }
    }

    public void ValueChanged(float newValue)
    {

    }
}

And can get the ValueChanged to fire using the following:

    AGuage n = new AGuage();

    n.Value = Pressure_Gauge.Value;

Which fires everytime the Pressure_Gauge.Value is updated.

The issue, or last hurdle, I am facing now is this part:

public void ValueChanged(float newValue)
{
  Form1.Pressure_Raw.text = "Working";
}

I want to update the label's text on form1 usingthe above method, however I get an error saying: An object reference is required for the nonstatic field, method, or property.

I'm not sure how to do this, I've read some information about Static properties, but how would I update the label's text value from within this?

Thanks.

like image 543
LBPLC Avatar asked Jan 25 '16 12:01

LBPLC


Video Answer


2 Answers

This might help. You could add an event and subscribe to it in your form.

For example:

public class AGauge {

    // You can either set the Value this way
    public float Value {
        get {return this.Value;}
        set 
        {
             // (1)
             // set "Value"
             this.Value = value;
             // raise event for value changed
             OnValueChanged(null);
        }
    }

    // create an event for the value change
    // this is extra classy, as you can edit the event right
    // from the property window for the control in visual studio
    [Category("Action")]
    [Description("Fires when the value is changed")]
    public event EventHandler ValueChanged;

    protected virtual void OnValueChanged(EventArgs e)
    {
        // (2)
        // Raise the event
        if (ValueChanged != null)
            ValueChanged(this,e);
    }

}

public Form1 : Form {
    // In form, make your control and add subscriber to event 
    AGauge ag = new AGauge();
    // (3)
    ag.ValueChanged += UpdateTextBox;

    // (4)
    public void UpdateTextBox(object sender, EventArgs e) 
    {
        // update the textbox here
        textbox.Text = ag.Value;
    }
}

Here's how this works: At (3) you add a subscriber to the ag.ValueChanged event as described HERE. When you go to change ag.Value, you get to (1), where Value is changed and OnValueChanged is called. This gets you to (2), where the ValueChanged event is raised. When this happens, all subscribers to that event are "notified" and call their respective methods. So when you get to (2), (4) ends up getting called because "UpdateTextBox" was set as a subscriber to the ValueChanged event. It's a bit tricky, but it is very useful.

Or if you want to continue with how you're trying to do it, you need to do this:

public class AGuage
{
    private float _value;

    // create object of Form1 for reference
    private Form1 form1;

    // pass reference to form1 through constructor
    public AGauge(Form1 form1)
    {
        // assign
        this.form1 = form1;
    }

    public float Value
    {
        get
        {
            return this._value;
        }
        set
        {
            this._value = value;
            this.ValueChanged(this._value);
        }
    }

    public void ValueChanged(float newValue)
    {
        // use the form1 reference
        this.form1.Pressure_Raw.Text = "Working";
    }
}

And then do this:

// if creating the AGauge object in Form1, pass "this" to the object
AGuage n = new AGuage(this);

I highly recommend you don't do it this way as this breaks the generics rule for OOP. Which means, if you try to use this AGauge control anywhere else other than in Form1, it will not work the same way. I recommend doing it with events like I have described above. It's much more universal.

like image 80
mike Avatar answered Oct 07 '22 10:10

mike


You need to make your AGauge implement INotifyPropertyChanged and notify the property changing on Value. There's enough information on Google on how to do this and has been discussed hundreds of times in StackOverflow.

Then, you will need to use a Binding to bind your textbox to the AGauge value. Since you need to convert, you'll need to provide formatting and optionally parsing.

This should be something like:

var binding = new Binding("Text", myAgaugeControl, "Value");
binding.Format += BindingFormat;
binding.Parse += BindingParse;
myTextBox.DataBindings.Add(binding);

BindingFormat and BindingParse should be the converters. Format would be for converting the gauge's value to the textbox string. The most simple:

void BindingFormat(object sender, ConvertEventArgs e)
{            
    e.Value = e.Value.ToString();
}

BindingParse would be the opposite: if the textbox text changes, you need to parse the text and convert it to a value AGauge can understand. I'll let you figure this out.

More information on Binding, Format and Parse

like image 23
Jcl Avatar answered Oct 07 '22 10:10

Jcl