值更改时触发事件C#

值更改时触发事件C#,c#,winforms,C#,Winforms,我试图监视一个值,当它被更改时,在执行一些计算并得到结果后更新一个文本字段 我试图监视的值来自AGauge属性(自定义控件)。我想在AGauge.Value更改时更新文本字段 我看了一些问题,例如,但我真的不明白这是如何工作的,或者我需要改变什么才能得到我想要的结果 有谁能更好地解释一下我需要做什么才能让这一切顺利进行 agage.Value是一种float类型,以防您怀疑 提前谢谢 更新1 现在,我已将以下代码添加到我的项目中: public class AGuage { privat

我试图监视一个值,当它被更改时,在执行一些计算并得到结果后更新一个文本字段

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

我看了一些问题,例如,但我真的不明白这是如何工作的,或者我需要改变什么才能得到我想要的结果

有谁能更好地解释一下我需要做什么才能让这一切顺利进行

agage.Value
是一种
float
类型,以防您怀疑

提前谢谢

更新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)
    {

    }
}
并且可以使用以下命令将
值更改为

    AGuage n = new AGuage();

    n.Value = Pressure_Gauge.Value;
每次更新
压力表值时都会触发

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

public void ValueChanged(float newValue)
{
  Form1.Pressure_Raw.text = "Working";
}
我想使用上述方法更新
form1
上的标签文本,但是我得到一个错误,即:
非静态字段、方法或属性需要对象引用

我不知道如何做到这一点,我已经阅读了一些关于静态属性的信息,但是如何从中更新标签的文本值呢


谢谢。

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

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

这应该是这样的:

var binding = new Binding("Text", myAgaugeControl, "Value");
binding.Format += BindingFormat;
binding.Parse += BindingParse;
myTextBox.DataBindings.Add(binding);
BindingFormat
BindingParse
应该是转换器<代码>格式
用于将仪表值转换为文本框字符串。最简单的是:

void BindingFormat(object sender, ConvertEventArgs e)
{            
    e.Value = e.Value.ToString();
}
BindingParse
则相反:如果文本框文本发生更改,则需要解析文本并将其转换为
可以理解的值。我会让你弄明白的


有关的详细信息,以及

您需要做的是为Value属性创建自定义setter。每次设置值时,您的代码都会调用钩子方法,我称之为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.
    }
}
也许会有帮助。您可以添加一个事件并在表单中订阅它

例如:

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.ValueChanged事件添加订户,如所述。 当您转到change ag.Value时,您将进入(1),其中Value被更改,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);

我强烈建议您不要这样做,因为这违反了面向对象编程的泛型规则。这意味着,如果您尝试在Form1之外的任何其他地方使用此AGauge控件,它将不会以相同的方式工作。我建议用我上面描述的事件来做。它更具通用性。

一个简洁的选择是使用微软的反应式框架(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
公共类AGuage
{
私人浮点数;
私有主体_值=新主体();
公众浮动价值
{
获取{返回_值;}
设置
{
_价值=价值;
_值。OnNext(值);
}
}
公共可观测值
{
获取{return_values.AsObservable();}
}
}
现在,您可以执行以下操作:

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
var aGuage=new aGuage();
变量查询=
从aGuage.Values中的值
其中值>5.0f&&value<20.0f//过滤
选择值*150f+45.3f//计算
风险值订阅=
query.Subscribe(值=>
{
/*对过滤后的计算值执行操作(&C)*/
});
aGuage.Value=2.1f;//查询。订阅不启动
aGuage.Value=12.4f;//查询。订阅会启动
aGuage.Value=202.1f;//查询。订阅不启动

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

您链接的问题已经有了一些很好的建议,特别是。你到底不明白什么?如果这太棘手,您可以只更新用户控件的属性设置器中的文本字段,尽管这没有那么好。请在标记中指定您使用的是
winforms
还是
wpf
。提到的问题是wpf(意思是在winforms中不起作用)或者到底是什么问题?对不起,是在winforms中。这就解释了为什么它不起作用了!您需要重写Value属性。如果您可以修改AGauge,我建议在每次更新属性时触发事件/将表单上的文本框的引用添加到AGauge控件可能会很麻烦。这是一个有效的方法,但会增加AGauge的开销,并降低其对其他应用程序的可移植性。我得到错误信息
“AGuage.Value.get”必须声明一个主体,因为它没有标记为抽象、外部、,或部分
尝试此方法时,还必须传递对表单的引用,以便AGauge可以访问文本框i将正文添加到属性的