如何在变量值改变时触发事件?

时间:2011-04-30 14:21:31

标签: c# visual-studio silverlight windows-phone-7 event-handling

我目前正在使用Visual Studio在C#中创建一个应用程序。我想创建一些代码,以便当变量的值为1时,执行某段代码。 我知道我可以使用if语句,但问题是该值将在异步进程中更改,因此从技术上讲,if语句可以在值更改之前被忽略。

是否可以创建事件处理程序,以便在变量值更改时触发事件?如果是这样,我该怎么做?

完全有可能我误解了if语句是如何工作的!任何帮助将不胜感激。

6 个答案:

答案 0 :(得分:104)

对我而言似乎想要创建一个属性。

public int MyProperty
{
    get { return _myProperty; }
    set
    {
        _myProperty = value;
        if (_myProperty == 1)
        {
            // DO SOMETHING HERE
        }
    }
}

private int _myProperty;

这允许您在属性值更改时运行一些代码。如果你愿意的话,你可以在这里举办活动。

答案 1 :(得分:55)

只要字段的值发生变化,您就可以使用属性设置器来引发事件。

您可以拥有自己的EventHandler委托,也可以使用着名的System.EventHandler委托。

通常有一种模式:

  1. 使用事件处理程序委托(具有EventArgs类型的参数)定义公共事件。
  2. 定义名为OnXXXXX的受保护虚拟方法(例如OnMyPropertyValueChanged)。在此方法中,您应检查事件处理程序委托是否为null,如果不是,则可以调用它(这意味着有一个或多个方法附加到事件委托)。
  3. 只要您想通知订阅者某些内容已发生变化,请调用此受保护的方法。
  4. 这是一个例子

    private int _age;
    
    //#1
    public event System.EventHandler AgeChanged;
    
    //#2
    protected virtual void OnAgeChanged()
    { 
         if (AgeChanged != null) AgeChanged(this,EventArgs.Empty); 
    }
    
    public int Age
    {
        get
        {
             return _age;
        }
    
        set
        {
             //#3
             _age=value;
             OnAgeChanged();
        }
     }
    

    这种方法的优点是,如果需要,您可以让任何其他想要从您的类继承的类更改行为。

    如果要捕获正在引发的其他线程中的事件,则必须注意不要更改在另一个线程中定义的对象的状态,这将导致抛出跨线程异常。要避免这种情况,您可以在要更改其状态的对象上使用Invoke方法,以确保更改发生在事件已引发的同一个线程中,或者您正在处理Windows窗体时可以使用BackgourndWorker在并行线程中做很好的事情。

答案 2 :(得分:39)

.NET框架实际上提供了一个接口,可用于在属性发生更改时通知订阅者:System.ComponentModel.INotifyPropertyChanged。此接口有一个事件PropertyChanged。它通常在WPF中用于绑定,但我发现它在业务层中用作标准化属性更改通知的方法。

就线程安全而言,我会在设置器中设置一个锁,这样你就不会遇到任何竞争条件。

以下是我在代码中的想法:):

public class MyClass : INotifyPropertyChanged
{
    private object _lock;

    public int MyProperty
    {
        get
        {
            return _myProperty;
        }
        set
        {
            lock(_lock)
            {
                //The property changed event will get fired whenever
                //the value changes. The subscriber will do work if the value is
                //1. This way you can keep your business logic outside of the setter
                if(value != _myProperty)
                {
                    _myProperty = value;
                    NotifyPropertyChanged("MyProperty");
                }
            }
        }
    }

    private NotifyPropertyChanged(string propertyName)
    {
        //Raise PropertyChanged event
    }
    public event PropertyChangedEventHandler PropertyChanged;
}


public class MySubscriber
{
    private MyClass _myClass;        

    void PropertyChangedInMyClass(object sender, PropertyChangedEventArgs e)
    {
        switch(e.PropertyName)
        {
            case "MyProperty":
                DoWorkOnMyProperty(_myClass.MyProperty);
                break;
        }
    }

    void DoWorkOnMyProperty(int newValue)
    {
        if(newValue == 1)
        {
             //DO WORK HERE
        }
    }
}

希望这有用:)

答案 3 :(得分:9)

只使用属性

int  _theVariable;
public int TheVariable{
  get{return _theVariable;}
  set{
    _theVariable = value; 
    if ( _theVariable == 1){
      //Do stuff here.
    }
  }
}

答案 4 :(得分:1)

您可以使用通用类:

class Wrapped<T>  {
    private T _value;

    public Action ValueChanged;

    public T Value
    {
        get => _value;

        set
        {
            OnValueChanged();
            _value = value;
        }
    }

    protected virtual void OnValueChanged() => ValueChanged?.Invoke() ;
}

,将能够执行以下操作:

var i = new Wrapped<int>();

i.ValueChanged += () => { Console.WriteLine("changed!"); };

i.Value = 10;
i.Value = 10;
i.Value = 10;
i.Value = 10;

Console.ReadKey();

结果:

changed!
changed!
changed!
changed!
changed!
changed!
changed!

答案 5 :(得分:1)

一种简单的方法涉及对变量使用get和set函数


    using System;
    public string Name{
    get{
     return name;
    }
    
    set{
     name= value;
     OnVarChange?.Invoke();
    }
    }
    private string name;
    
    public event System.Action OnVarChange;