all groups > c# > october 2006 >
You're in the

c#

group:

Subscribe and unsubscribe to Windows.Forms.Controls events automatically


Subscribe and unsubscribe to Windows.Forms.Controls events automatically Douglas Peterson
10/11/2006 8:00:06 PM
c#: I created the following code:

private struct StackItem
{
public EventHandler theEvent, theHandler;
public StackItem(EventHandler theEvent, EventHandler theHandler)
{
this.theEvent = theEvent;
this.theHandler = theHandler;
}
}

protected void AddHandler(EventHandler theEvent, EventHandler theHandler)
{
theEvent += theHandler; // add handler to event
stack.Push(new StackItem(theEvent, theHandler)); // note the fact that we
did so
}

public virtual void Dispose()
{
while (stack.Count > 0)
{
StackItem si = (StackItem)stack.Pop();
si.theEvent -= si.theHandler; // remove the handler from the event
}
}

So that my derived classes can register for various events of various
controls on my form without having to make certain to add both the subscribe
and unsubscribe lines of code. However, the following code:

AddHandler(form.listView.SizeChanged, new
System.EventHandler(this.listView_SizeChanged));

gives the following error:

"The event 'System.Windows.Forms.Control.SizeChanged' can only appear on the
left hand side of += or -="

I assume this is some attribute of the SizeChanged member of the various
stock controls. Is there any way around this?

Why do I need to unsubscribe? Because I'm using objects to implement various
states in my application. When the app changes states it needs to unhook the
current state object from all events so that the new state can take over.

Re: Subscribe and unsubscribe to Windows.Forms.Controls events automatically Ignacio Machin ( .NET/ C# MVP )
10/11/2006 9:51:14 PM
Hi

Did you used to program in VB.NET ?

This is usually the approach taken in Vb.net to add a handler to an event,
in C# you use:
form.listView.SizeChanged += new
System.EventHandler(this.listView_SizeChanged) ;



--
Ignacio Machin
machin AT laceupsolutions.com


[quoted text, click to view]

Re: Subscribe and unsubscribe to Windows.Forms.Controls events automatically Christof Nordiek
10/12/2006 12:00:00 AM
"Douglas Peterson" <Tergiver@nospam.msn.com> schrieb im Newsbeitrag
news:%23tb$hFZ7GHA.1188@TK2MSFTNGP05.phx.gbl...
[quoted text, click to view]

The cause is, that SizeChanged is an event and not a delegate field or
property.
Events can only be used on the left side of += or -= operators.
(An exception are field like events wich inside!! the class where they are
defined behave like fields of a delegate type.) Even if SizeChanged was a
field or property of a delegate type your code wouldn't work, because
delegates are imutable, and the operations would create only new delegate
instances wich will be stored in your stack item, but not in the Control.

[quoted text, click to view]


possible solutions:
1. for every Event make a static method, wich is subscribed once and calls
the appropriate handler on the actual stateobject.

2. make two methods wich do all the subscribing and unsubscribing of the
event.

3. store the old state object, and for every event make a method or
codeblock wich does the subscribing and the unsubscribing:
if (olsState != null)
control.Event -= oldState.Handler();
control.Event += newState.Handler();

4. in the StackItem store the MemberInfo of the event.

Re: Subscribe and unsubscribe to Windows.Forms.Controls events automatically Douglas Peterson
10/13/2006 8:52:12 AM

[quoted text, click to view]

This was my original method. The form handled the events and called virtual
members on the state objects. I didn't like it because it wasn't very
encapsulated.

[quoted text, click to view]

This is the way I'm doing it currently, the objects subscribe in their
constructors and unsubscribe in the virtual Dispose method. This is tedius
and prone to mistakes. If I don't find another solution, I'll stick to this.

[quoted text, click to view]

The different state objects don't all subscribe to the same events, thus the
desire for encapsulation.

[quoted text, click to view]

This looks promising. I don't know C# well enough at this point to make it
work so I am going to research it and learn something new.


There is a #5 as well that has since occurred to me:

5. Have the state objects create and destroy the controls.

Each state makes use of 95% of all the controls. The controls simply behave
a bit differently depending on the current state. There are quite a lot of
controls. So I don't like this one either.

Thanks for all the suggestions,
Douglas

Re: Subscribe and unsubscribe to Windows.Forms.Controls events automatically Douglas Peterson
10/13/2006 10:17:21 AM
After researching MethodInfo, turns out I need EventInfo. It works great!
Here is the final code:

private class StackItem
{
public object control;
public System.Reflection.EventInfo eventInfo;
public System.EventHandler handler;
public StackItem(object control, string eventName, System.EventHandler
handler)
{
this.control = control;
this.eventInfo = control.GetType().GetEvent(eventName);
this.handler = handler;
this.eventInfo.AddEventHandler(this.control, this.handler);
}
public void Dispose()
{
this.eventInfo.RemoveEventHandler(this.control, this.handler);
}
}

private System.Collections.Stack stack = null;

public void Dispose()
{
while (stack.Count > 0)
(this.stack.Pop() as StackItem).Dispose();
}

protected void AddHandler(object control, string eventName,
System.EventHandler handler)
{
if (this.stack == null)
this.stack = new Stack();
this.stack.Push(new StackItem(control, eventName, handler));
}


I simpy call AddHandler(form.listView, "SizeChanged", new
System.EventHandler(this.listView_SizeChanged)) in my derived State object's
constructor.

Thank you for your assistance,
Douglas

AddThis Social Bookmark Button