views:

132

answers:

2

Being relatively new to C#, I've been researching custom events recently, and while I think I now understand the basic pieces required to setup a custom event, I'm having trouble determining where each piece belongs. Specifically, here's what I'm trying to do.

I have a tree control that represents the layout of an internal data structure. When the data is rearranged in the tree (via drag/drop), I need to rearrange the underlying data structure to match.

So, I'm attempting to fire my own, custom event from within the "Drop" event handler of the tree control (after I've validated the drop). The idea being that a subscriber to my event would handle the reordering of the underlying data.

I'm just struggling to determine where each piece of event machinery should be created and/or used.

If someone could provide me with a basic sample of the above, that'd be great. For instance, maybe a simple example that sets up and fires a custom event from within an existing button_click event. That would seem to be a good simulation of what I'm trying to do.

Also, if my approach to the problem seems completely wrong, I'd like to know that also.

A: 

Everything belongs in the class which exposes the event:

public event EventHandler Drop;

protected virtual void OnDrop(EventArgs e)
{
    if (Drop != null)
    {
        Drop(this, e);
    }
}

If you have a custom EventArgs type, you'll want to use the generic EventHandler<MyEventArgs> delegate instead of EventHandler.

Is there anything else you weren't sure about?

John Saunders
Thanks for the input, it was helpful. Unfortunately, it's not enough for me to see my way through the forest. My fault, not yours...
Jeff Godfrey
-1: This code is not threadsafe - if drop is unassigned after the `if` a `NullReferenceException` will be thrown. You should be assigning the Drop event to an `EventHandler` delegate first.
Richard Szalay
+1  A: 

You need to declare the prototype for your event handler, and a member variable to hold event handlers that have been registered in the class owns the treeview.

// this class exists so that you can pass arguments to the event handler
//
public class FooEventArgs : EventArgs
{
    public FooEventArgs (int whatever) 
    { 
       this.m_whatever = whatever; 
    }

    int m_whatever;
}

// this is the class the owns the treeview
public class MyClass: ...
{
    ...

    // prototype for the event handler
    public delegate void FooCustomEventHandler(Object sender, FooEventArgs args);

    // variable that holds the list of registered event handlers
    public event FooCustomEventHandler FooEvent;

    protected void SendFooCustomEvent(int whatever)
    {
        FooEventArgs args = new FooEventArgs(whatever);
        FooEvent(this, args);
    }

    private void OnBtn_Click(object sender, System.EventArgs e)
    {
        SendFooCustomEvent(42);
    }

    ...
}

// the class that needs to be informed when the treeview changes
//
public class MyClient : ...
{
    private MyClass form;

    private Init()
    {
       form.FooEvent += new MyClass.FooCustomEventHandler(On_FooCustomEvent);
    }

    private void On_FooCustomEvent(Object sender, FooEventArgs args)
    {
       // reorganize back end data here
    }

}
John Knoeller
Thanks! This (a complete example) is exactly what I needed. With a little massaging, I was able to get this working in the context of my application.
Jeff Godfrey