return values from events, eventArgs

J

Jack Addington

I have a 3rd party object that fires an itemchanged event when someone edits
some data on a form. This event has a custom eventArgs that has a field
called ActionCode. In the code of the event, if you set this ActionCode to
various values the control will respond in various ways (reject, reject
change field, accept, etc). I am trying to understand exactly how that
works as I am trying to extend the control and add more processing s events.
In my previous exposure to languages, the events simply had return codes and
I could intercept them in a descendent or ancestor and proccess them.
Obviously it was hiding the whole idea of delegates and such.

I could implement all my code as methods but I would like to be able to put
the code on a form, and still be able to extend or override the framework
code.. I've got a few problems understanding the exact behaviour of the
EventArgs (how to return values) and also how to 'post' and event to fire
when there is no more processing to do. Also how does the eventArgs really
work when there are multiple subscribers? If the first one in the delegate
thread fires should the second one be getting any updates?

This is what I would like to do for letting the user add/insert a new row.
There is a method on the control called InsertRow (int beforeRow){}, 0 = add
to end.

I'm going to define the AddRowEventArgs as (int beforeRow, int actionCode,
int NewRow).

1) User hits button or right mouse to 'Add a new Row'. This calls the
InsertRow() event

event AddRow(obj Sender, AddRowEventArgs e){
e.beforeRow = 0; (this should be set by the method calling the event but
just in case)
trigger event InsertRow(0)
}

event InsertRow(obj Sender, AddRowEventArgs e){
trigger event PreInsertRow(Sender, e)
if (e.ActionCode = ActionCode.DoNotContinue) then return;

e.newRow = this.InsertRow(e.beforeRow)

// run this event after all other code (descendent etc has finished
processing)
post event PostInsertRow(Sender, e)
}

In my 'PowerBuilder' days, I would simply have created the events with a
return code and checked that. I know the compiler lets me do that but it
didn't seem to clear how to capture that in .Net. Not that I'm all that
sure how to capture the EventArgs either. Do I need to be passing them as
ref? What I have so far is obviously a work in progress. I started using
return values but suddenly I had concerns about what to do when 1) there are
layers of descendants and 2) when other events subscribe.

I'm starting to think is that maybe it is the OnEventFire method that is
really suppose to be doing the logically sorting out of return code /
eventArgs and if it finds one that returns -1 or something it jumps in an
processes it?

public delegate int DWAddRowEventHandler (Object sender, RowActionEventArgs
args);
public delegate int DWPreInsertRowEventHandler (Object sender,
RowActionEventArgs args);
public delegate int DWInsertRowEventHandler (Object sender,
RowActionEventArgs args);
public delegate int DWPostInsertRowEventHandler (Object sender,
RowActionEventArgs args);

public event DWAddRowEventHandler DWAddRow ;
public event DWPreInsertRowEventHandler DWPreInsertRow ;
public event DWInsertRowEventHandler DWInsertRow ;
public event DWPostInsertRowEventHandler DWPostInsertRow ;

protected virtual int DWPreInsertRow(Object sender, RowActionEventArgs
args){return 0;}
protected virtual int DWInsertRow( Object sender, RowActionEventArgs args)
{
int rc;

rc = this.OnDWPreInsertRow(e);
if (rc < 0) return rc;

rc = this.InsertRow( beforeRow );

this.DWPostAddRow(); //************ should this be something like
start a new low priority thread? Seems a touch complicated to do that?

return rc;
}

protected virtual int DWPostInsertRow(Object sender, RowActionEventArgs
args){}

protected virtual int OnDWAddRow( RowActionEventArgs e )
{
if (DWAddRow != null) {
e.beforeRow = 0;
return DWAddRow( this, e);
}
return 0;
}

protected virtual int OnDWPreInsertRow( RowActionEventArgs e )
{
if (DWAddRow != null) return DWAddRow( this, e);
return 0;
}

protected virtual int OnDWInsertRow( RowActionEventArgs e )
{
if (DWAddRow != null) return DWAddRow( this, e);
return 0;
}

protected virtual int OnDWPostInsertRow( RowActionEventArgs e )
{
if (DWAddRow != null) return DWAddRow( this, e);
return 0;
}

Thanks so much for any help. I mostly trying to avoid do a bunch of useless
work because I don't quite understand a couple of concepts.

jack
 
J

Jack Addington

ok, I think I cleared some things up myself but I still have a number of
questions. Please correct me if I am wrong:

1) EventArgs is an object so, everytime its passed around it retains all its
data because its an object, not a int or something.

2) In order to check the progress/results from a chain of delgates (from
inheritence) is to use the GetInvocationList and then manually call them one
at a time and check the return code / EventArgs. This would happen in the
OnXXXEvent method

3) Haven't proven to myself yet but if I wanted the descendent class to
completely override the ancestor event then I need to override the
OnXXXEvent method and somehow ignore the ancestor callbacks? Not sure how
to do this, or is there an easier way? Can I ask a Delete if it is callback
to the current object or an ancestor of the current object? Makes sense in
my mind...

Questions:

A) Is it better to do all the processing based on the EventArgs or use a
return value? Is there a standard or preferred approach?

B) Should I be exposing (ie Public) the Virtual On method so that it can be
called by a button or right mouse click? or should I build an intermediate
layer or something?

C) How to do handle issue 3 above.

thx so much
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top