在值更改 C# 时触发事件

本文关键字:事件 | 更新日期: 2023-09-27 18:31:41

我正在尝试监视一个值,当它被更改时,在对结果执行一些计算后更新文本字段。

我尝试监视的值来自AGauge属性(自定义控件)。我想在AGauge.Value更改时更新文本字段。

我已经看过诸如"这个"之类的问题,但我真的不明白这是如何工作的,或者我需要更改什么才能获得我正在寻找的结果。

谁能更好地解释我需要做什么才能使其工作?

AGuage.Valuefloat类型,以防您想知道。

提前谢谢。

更新 1

现在,我已将以下代码添加到我的项目中:

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)
    {
    }
}

并可以使用以下内容使ValueChanged触发:

    AGuage n = new AGuage();
    n.Value = Pressure_Gauge.Value;

每次更新Pressure_Gauge.Value时都会触发。

我现在面临的问题,或者说最后一个障碍是这部分:

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

我想使用上述方法在form1上更新标签的文本,但是我收到一个错误说:An object reference is required for the nonstatic field, method, or property.

我不确定如何做到这一点,我已经阅读了一些有关静态属性的信息,但是我将如何从中更新标签的文本值?

谢谢。

在值更改 C# 时触发事件

这可能会有所帮助。您可以添加事件并在表单中订阅它。

例如:

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;
    }
}

这是如何工作的:在 (3) 处,将订户添加到 AG。值更改事件,如此处所述。当你去改变AG时。Value,你得到(1),其中值被更改,OnValueChanged被调用。这会将您带到 (2),其中引发 ValueChanged 事件。发生这种情况时,该事件的所有订阅者都会收到"通知"并调用其各自的方法。因此,当您到达 (2) 时,(4) 最终会被调用,因为"UpdateTextBox"被设置为ValueChanged 事件的订阅者。这有点棘手,但它非常有用。

或者,如果您想继续尝试这样做,则需要执行以下操作:

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";
    }
}

然后这样做:

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

我强烈建议你不要这样做,因为这违反了 OOP 的泛型规则。这意味着,如果您尝试在 Form1 以外的任何其他位置使用此 AGauge 控件,它将不以相同的方式工作。我建议使用我上面描述的事件来执行此操作。它更加普遍。

您需要

使AGauge实现INotifyPropertyChanged并在Value上通知属性更改。谷歌上有足够的关于如何做到这一点的信息,并且在StackOverflow中已经讨论了数百次。

然后,需要使用Binding将文本框绑定到AGauge值。由于需要转换,因此需要提供格式设置和选择性解析。

这应该是这样的:

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

BindingFormatBindingParse应该是转换器。 Format用于将仪表的值转换为文本框字符串。最简单的:

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

BindingParse则相反:如果文本框文本发生更改,则需要解析文本并将其转换为AGauge可以理解的值。我会让你弄清楚的。

有关绑定、格式和解析的更多信息

您需要做的是为 Value 属性创建自定义资源库。每次设置值时,您的代码都会调用您的钩子方法,我称之为 ValueChanged()。在该方法中,您可以执行计算,然后将文本字段设置为结果。

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)
    {
        // Action to perform on value change
        // Update a text field after performing some calculations with a result.
    }
}

一个不错而干净的选择是使用Microsoft的响应式框架(NuGet "Rx-WinForms")。它允许您以类似 LINQ 的方式处理可观察量(而不是可枚举量)。

您的类将如下所示:

public class AGuage
{
    private float _value;
    private Subject<float> _values = new Subject<float>();
    public float Value
    {
        get { return _value; }
        set
        {
            _value = value;
            _values.OnNext(value);
        }
    }
    public IObservable<float> Values
    {
        get { return _values.AsObservable(); }
    }
}

现在你可以做这样的事情:

var aGuage = new AGuage();
var query =
    from value in aGuage.Values
    where value > 5.0f && value < 20.0f //filtering
    select value * 150f + 45.3f; //computation
var subscription =
    query.Subscribe(value =>
    {
        /* do something with the filtered & computed value */
    });
aGuage.Value = 2.1f; // query.Subscribe doesn't fire
aGuage.Value = 12.4f; // query.Subscribe DOES fire
aGuage.Value = 202.1f; // query.Subscribe doesn't fire

如果要关闭对值的订阅,只需调用 subscription.Dispose()