Click here to Skip to main content
15,867,308 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi people, I'm not professional in C#, so sometimes I face some probs like this:
I can define an object containing properties using get{ }; set{ }, how can I define an event to this object? (like OnChange event)

Thanks.
Posted

As Christian said, you can't use auto properties if you want to do any validation or event raising in the setter.

To do it yourself and raise an event, this is the basic pattern:
C#
using System;

public class SampleClass
{
    public event EventHandler ValueChanged;

    private int value;

    public int Value
    {
        get { return value; }
        set
        {
            if (this.value != value)
            {
                this.value = value;
                OnValueChanged(EventArgs.Empty);
            }
        }
    }

    protected virtual void OnValueChanged(EventArgs e)
    {
        EventHandler eh = ValueChanged;
        if (eh != null)
            eh(this, e);
    }
}
 
Share this answer
 
Comments
Kubajzz 28-Aug-10 7:05am    
Reason for my vote of 5
Simply perfect answer
You need to not use the auto generated stuff you illustrated, but define a private member that is explicity get and set in your property. Then you can also define an event and fire it within your setter ( I assume ).
 
Share this answer
 
Comments
Alireza Hajihasani 28-Aug-10 5:05am    
May I ask you to explain more?
Christian Graus 28-Aug-10 5:07am    
private string _myString;
public Event void StringChanged(string newval);
public StringChanged OnStringChanged = null;

public string MyString
{
get {return _myString;}
set
{
_myString = value;
if(OnStringChanged != null) OnStringChanged(value);

}

That's rough as guts and untested, but it's the general idea.


}
Alireza Hajihasani 28-Aug-10 5:49am    
Thank's man, see Answer2.
Kubajzz 28-Aug-10 7:02am    
Reason for my vote of 3
A good solution, but far from perfect...
Ok, here is a complete solution which roughly corresponds to commonly recommended best practices... I suggest that you read an article about the basics of delegates and events, that will help you a lot.

C#
class MyClass {
  private string someValue; // Backing field

  public string SomeValue {
    get { return someValue; }
    set {
      // The event only needs to be raised when the value actually changes
      if (value == someValue) return;
      someValue = value;
      OnSomeValueChanged();
    }
  }

  public event EventHandler SomeValueChanged;

  private void OnSomeValueChanged() {
    // This is the simplest way to raise the event (and it is NOT thread safe)
    if (SomeValueChanged != null) SomeValueChanged(this, EventArgs.Empty);
  }
}


You may want to use a different delegate type than EventHandler and create a custom EventArgs class... The example I gave you is just a start.
 
Share this answer
 
Comments
DaveyM69 28-Aug-10 6:53am    
This is good except for your OnSomeValueChanged method. There are two problems.
1. There is a possible race condition. SomeValueChnged could become null between the null check and the next line where you fire the event. To guard against this, make a copy of SomeValueChanged:
EventHandler eh = SomeValueChanged;
then use eh from that point.
2. It's generally better to pass the args to the OnXxx method as a parameter and make the OnXxx method protected virtual. This makes it possible to be easily overridden later in deriving classes.
Kubajzz 28-Aug-10 7:01am    
I know all that.

1. That's why there's a comment saying it's not a thread-safe way to raise the event. I only provided the simplest and most basic solution.

2. I know the method should be protected virtual according to the recommended practices. However, I'll say it again: I wanted to provide the simplest possible solution just to show the basics, because the guy who originally asked the question obviously doesn't know anything about events... That's why I ignored this rule.
You are right though that my OnSomeValueChanged method should take an EventArgs parameter (although it's useless) to keep the common pattern... Your solution is somewhat more complete.
Thank's man to reply; but I've got some errors using the code:
private string _myString;
public event *1 void StringChanged*2(string *3 newval *4 );
public *5 StringChanged OnStringChanged = null;
public string MyString
{
get
{
return _myString;
}
set
{
_myString = value;
if(OnStringChanged != null)
{
OnStringChanged(value);
}
}
}
=======================
1)Field cannot have void type
2)Expected ; or = (cannot specify constructor arguments in declaration)
3)Invalid expression term 'string'
4)Invalid token ')' in class, struct, or interface member declaration
5)'... .StringChanged' is a 'field' but is used like a 'type'
 
Share this answer
 
Comments
Christian Graus 28-Aug-10 5:51am    
I was trying to use the event keyword b/c I've been told there's advantages. Replace 'event' with 'delegate'.
Alireza Hajihasani 28-Aug-10 6:58am    
Thank's for answer.
Kubajzz 28-Aug-10 7:04am    
Reason for my vote of 1
This is not an answer, comments should be used for this stuff...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900