Thanks Jeff for the input, see comments inline (hope this didn't get too
long)
amazingly I finally got an event working after several tries to follow the
tutorial on this page:
http://msdn.microsoft.com/en-us/library/w369ty8x.aspx
Jeff Johnson said:
Events require a "type". Specifically, they need to be of some type of
delegate.
snip
So you might do this:
do you put this (EventArg class) in it's own cs file? or create it as a
separate class inside the cs file holding the 'event publishing' class? I
ended up using a separate class file, not sure if that matters, but the
class raising the event(cLispFile) and the class subscribing the event
(window.xaml.cs)- both need to see this class.
"//Declare your class at a scope visible to both your publisher and
subscriber classes, "
public class PositionEventArgs : EventArgs
{
snip
}
I highly recommend you follow the convention of putting "EventArgs" at the
end of the class name as I did above.
yep, that tutorial also had that convention
Then to raise the event you simply call the event name itself as if it
were a method (because it basically is). To do this it's best to set up a
common method to do the work, and the naming convention is
"On<YourEventName>":
// I'm declaring this as void but it doesn't have to be. If this
// is one of those events that receives data from the subscriber,
// (like a cancelable event) you might want this handler to return
// that data.
private void OnCommentPosition(int position)
{
EventHandle<PositionEventArgs> threadSafeCopy = CommentPosition;
if (threadSafeCopy != null)
{
// I'm creating a new PositionEventArgs object on the fly,
// but if the subscriber were going to modify its properties,
// I'd want to create the object in a variable, pass that in
// to the call below, and then examine the properties after
// the call.
threadSafeCopy(this, new PositionEventArgs(position));
}
}
that's a little different from what i came up with per the tutorial...i'll
have to study this a bit to understand the pros/cons of each way....
here's what i ended up with
//from example next step
// Wrap event invocations inside a protected virtual method
// to allow derived classes to override the event invocation
behavior
protected virtual void OnRaiseCustomEvent(CommentEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is
raised.
EventHandler<CommentEventArgs> handler = RaiseCustomEvent;
// Event will be null if there are no subscribers
if (handler != null)
{
// Use the () operator to raise the event.
handler(this, e);
}
}
And then when you need to raise the event you simply do:
OnCommentPosition(theCurrentPosition);
in my case it ended up;
this happens in a loop reading through the file line by line, each pass
calls this with the current data for that line
(i'll be adding two more string args, but for now this to get the structure
working)
OnRaiseCustomEvent(new CommentEventArgs(ThisComment, pos));
so i see i can either pass the args(your example) or the EventArgs object
(my sample) at this point
that makes sense.
if all you care about is actually setting up and raising events, this is
all you need.
actually the second half of all this is subscribing to the event...
in my case i put (in the window.xaml.cs) the following...
(seems to work, don't know if it's 'right' so to speak
class Subscriber
{
private System.Windows.Controls.ListBox lb;
public Subscriber(cLispFile cf, System.Windows.Controls.ListBox
LB)
{
lb = LB;
// Subscribe to the event using C# 2.0 syntax
cf.RaiseCustomEvent += HandleCustomEvent;
}
// Define what actions to take when the event is raised.
void HandleCustomEvent(object sender, CommentEventArgs e)
{
lb.Items.Add(e.Position);
}
}
then to create the class that raises the event and the one that subscribes
to it
private void button1_Click(object sender, RoutedEventArgs e)
{
cLispFile cf = new cLispFile("path to file");
Subscriber sub1 = new Subscriber(cf, this.listBox1);
cf.ReadFile();
One more thing: I must say I don't care for the name of your event. Events
should have a verb in them, as they represent something happening. Change.
Click. Render. CommentPosition sounds like a couple of nouns. By the name
of the event alone I, as "some other programmer," have no idea what sort
of action it represents.
that makes sense, i could change it to DetectComment or ReportComment or
something like that.
I'm probably using this event in a goofy way (not being a 'real' programmer)
i'm parsing lisp code text files, detecting and removing comments to create
a "clean" version
just as a way to watch what's going on and see if i'm correctly trapping all
the comments, i created a form with 3 listboxes to show the original lines,
the comments found, and the resulting "cleaned" version.
to see if my string.substring(int,int) was using the correct numbers i added
a listbox to show what position the comment was found in.
originally i was populating 4 stringbuilders with the content for the 4
listboxes, then after the loop through the file populate the listboxes from
the stringbuilders
then the idea of using an event inside the loop instead of filling
stringbuilders and later reading them back occurred to me and that's what
started my excursion into learning how to do events.
vb6 was so easy i didn't realize how convoluted it would become with dotnet.
anyway thanks again for the input and i appreciate any comments you have on
what i've done compared to what you showed as well, especially the
subscriber part as you hadn't addressed that
thanks
mark