Ivan-Mark Debono
Ivan-Mark Debono

Reputation: 16280

C# Raising event to inherited classes only

I have a generic user control:

public partial class SearchBoxGeneric<T> : UserControl
{
    protected class RecordFoundEventArgs
    {
        public T Record { get; private set; }

        public RecordFoundEventArgs(T record)
        {
            this.Record = record;
        }
    }
    protected event EventHandler<RecordFoundEventArgs> RecordFound;

    //Called from search button
    public void Find()
    {
        //1. Search for record in the db
        //2. Raise event to derived classes
    }
}

I have user controls that inherit from this generic control. Now when I search for a record from the db, I would like to the raise the event to the inherited control.

How can I do this?

Upvotes: 0

Views: 110

Answers (2)

Adriano Repetti
Adriano Repetti

Reputation: 67080

To raise an event you use same code you would use for a public event:

public void Find()
{
    T record = FindRecordCore();
    if (record != default(T))
    {
        var recordFound = RecordFound;
        if (recordFound != null)
            recordFound(this, new RecordFoundEventArgs(record));
    }
}

To follow normal pattern for events you should add a specific OnXyz method:

protected virtual void OnRecordFound(RecordFoundEventArgs e)
{
    var recordFound = RecordFound;
    if (recordFound != null)
        recordFound(this, e);
}

Invoked like this:

public void Find()
{
    T record = FindRecordCore();
    if (record != default(T))
        OnRecordFound(new RecordFoundEventArgs(record));
}

BUT What I would consider is if here an event is needed. Why don't you simply use a protected method? Events are notifications (or connection points) for external classes, derived classes can always simply override a class method. A protected event is something strange and you should ask yourself the reason for that:

protected virtual void OnRecordFound(T record)
{
    // Derived classes will handle "event" here
}

public void Find()
{
    T record = FindRecordCore();
    if (record != default(T))
        OnRecordFound(record);
}

Even if event was public if you follow normal events pattern (and you have a protected OnRecordFound method) usually derived classes should override OnRecordFound() and event RecordFound is used by external entities.

Upvotes: 2

Maarten
Maarten

Reputation: 22945

Events are normally fired so someone else can be notified when something happens.

public class SearchBox {
    public event EventHandler<RecordFoundEventArgs> RecordFound;

    protected virtual void OnRecordFound(RecordFoundEventArgs e) {
        var recordFound = RecordFound;
        if (recordFound != null) {
            recordFound(this, e);
        }
    }

    public void Find() {
        // ...

        // Fire event
        OnRecordFound(new RecordFoundEventArgs(...));
    }
}

// Usage
var searchBox = new SearchBox();
searchBox.RecordFound += (s, e) => { ... };
searchBox.Find();   // trigger the eventhandler we just defined

But if you have a derived class, it is more common to override the OnRecordFound method, and add the logic you need to run there.

public class SpecialSearchBox: SearchBox {
    protected override void OnRecordFound(RecordFoundEventArgs e) {
        base.OnRecordFound(e);

        // Do something extra
    }
}

Now whenever the event is fired, the logic in our derived class is run automatically.

If you have defined your event just to notify a derived class, it is probably easier to just define a virtual method that you can call from the base class.

Upvotes: 0

Related Questions