[Webinar] Streamline your web hosting managementRegister Today

x
?
Solved

events: problem with delegate

Posted on 2005-05-17
20
Medium Priority
?
684 Views
Last Modified: 2010-05-18
Hi experts:

I have created a user control that published an event called ClosePanel.

The user control is a panel with a button and other controls on it. The click onto the button triggers the ClosePanel event that is created as follows in my user control class:

       private static readonly object ClosePanelEventHandler = new object();

        public event EventHandler ClosePanel
        {
            add
            {
                this.Events.AddHandler(ClosePanelEventHandler, value);
            }
           
            remove
            {
                this.Events.RemoveHandler(ClosePanelEventHandler, value);
            }
        }


        private void OnClosePanel()
        {
            EventHandler handler = this.Events[ClosePanelEventHandler] as EventHandler;
            if (handler != null)
            {
                handler(this,EventArgs.Empty);
            }
        }


       private void uxCloseBtn_Click(object sender, System.EventArgs e)    // this triggers the event
       {
            OnClosePanel();
       }


   public class ClosePanelEventArgs : EventArgs   // Definition of the event class
    {
        private int id;
         
        private ClosePanelEventArgs()
        {
        }
     
        public ClosePanelEventArgs(int id)
        {
            this.id = id;
        }
     
        public int ID
        {
            get
            {
                return this.id;
            }
        }
    }

------

Now I try to add a custom control dynamically during runtime and I want to add the event handler to the dynamically created control:


       private void addLightControlPanel(string LightName)
        {
            int index = LightControlPanels.Count;
            LightControlPanel DynLCP = new LightControlPanel();
            DynLCP.lightControlName = LightName;
            DynLCP.BackColor = SystemColors.ControlLight;
            DynLCP.Location = new Point(10 + (index * 150),10);
            DynLCP.ClosePanel += new System.EventHandler(this.Panel_Closed);        // this line causes the problem: delegate is not matching...

            LightControlPanels.Add(LightName, DynLCP);
            this.uxDynLCPPnl.Controls.Add((LightControlPanel)LightControlPanels[LightName]);
        }

        private void Panel_Closed(object sender, ClosePanelEventArgs e)
        {
            LightControlPanel panel = (LightControlPanel) sender;

            string name = panel.lightControlName;
            Debug.WriteLine("Panel " + name + " pressed");
        }

As I am newbee I am just digging into events and delegates. I would be really happy, if you could correct my code and explain what I did wrong.

Thank you very much in advance!

0
Comment
Question by:i-Thomas
  • 9
  • 6
  • 5
20 Comments
 
LVL 23

Expert Comment

by:b1xml2
ID: 14021220
you have to declare a delegate:


       private static readonly object ClosePanelEvent = new object();

        public event ClosePanelEventHandler ClosePanel
        {
            add
            {
                this.Events.AddHandler(ClosePanelEvent, value);
            }
           
            remove
            {
                this.Events.RemoveHandler(ClosePanelEvent, value);
            }
        }


        private void OnClosePanel(ClosePanelEventArgs args)
        {
            ClosePanelEventHandler handler = this.Events[ClosePanelEvent] as ClosePanelEventHandler;
            if (handler != null)
            {
                handler(this,args);
            }
        }


       private void uxCloseBtn_Click(object sender, System.EventArgs e)    // this triggers the event
       {
            /// just adding a value to show you how to do it
            OnClosePanel(new ClosePanelEventArgs(10));
       }


public class ClosePanelEventArgs : EventArgs   // Definition of the event class
{
      public readonly int ID;
      
      
      public ClosePanelEventArgs(int ID)      
      {
            this.ID = ID;
      }
      
      
}
   
   
    public delegate void ClosePanelEventHandler(object sender,ClosePanelEventArgs args);
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 14021226
and here:
private void addLightControlPanel(string LightName)
{
      int index = LightControlPanels.Count;
      LightControlPanel DynLCP = new LightControlPanel();
      DynLCP.lightControlName = LightName;
      DynLCP.BackColor = SystemColors.ControlLight;
      DynLCP.Location = new Point(10 + (index * 150),10);
      DynLCP.ClosePanel += new ClosePanelEventHandler(this.Panel_Closed);      
      
      LightControlPanels.Add(LightName, DynLCP);
      this.uxDynLCPPnl.Controls.Add((LightControlPanel)LightControlPanels[LightName]);
}
0
 
LVL 9

Assisted Solution

by:BurntSky
BurntSky earned 800 total points
ID: 14021272
Call me crazy, but it seems like you're doing things the hard way.  Events are much easier than they appear.  Here's my standard model:

public delegate void ClosePanelEventHandler(object sender, ClosePanelEventArgs e);

public class ClosePanelEventArgs : EventArgs
{ ... }

public class Class1
{
   public event ClosePanelEventHandler ClosePanel;

   private void OnClosePanel()
   {
      if(this.ClosePanel != null)
         this.ClosePanel(this, new ClosePanelEventArgs(...));
   }
}

public class Class2
{
   private void SomeMethod()
   {
      Class1 c1 = new Class1();
      c1.ClosePanel += new ClosePanelEventHandler(this.c1_ClosePanel);
   }

   private void c1_ClosePanel(object sender, ClosePanelEventArgs e)
   {
      // ...
   }
}
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
LVL 23

Expert Comment

by:b1xml2
ID: 14021283
this is event optimisation only available in c#
0
 
LVL 9

Expert Comment

by:BurntSky
ID: 14021326
Yeah, my guess was he saw a bunch of VB.NET examples and transcribed them to C#.  Everything in C# is easier :)  Not to mention all the extra features.
0
 

Author Comment

by:i-Thomas
ID: 14021523
@b1xml2:

    public delegate void ClosePanelEventHandler(object sender,ClosePanelEventArgs args);

This belongs in the main class, not in the custom control, right?


@BurntSky:

Can you please explain the differences in your approach compared to that of b1xml2? It is hard for me to understand it instantly as I just started to learn about events / delegates! Thank you in advance!


0
 
LVL 9

Expert Comment

by:BurntSky
ID: 14022209
You can put the delegate anywhere you want; they don't even have to be inside a class.  In fact, I usually prefer to have them outside a class so they are at the same namespace level as my EventArgs class.

b1xml2 just refined your code a bit to solve your problem.  It should work just fine for you.  However, I just wanted to show you that theres an easier way to do event handling in c#.  The concepts are about the same; you still have to have the delegate, you still declare and raise the event, you just do it all in fewer lines of code.  If there's something about my code you don't understand, feel free to ask specifics so we can answer the issue your having trouble with more thoroughly.
0
 

Author Comment

by:i-Thomas
ID: 14022498
For sure I prefer the easier way, if this easier way does not bring disadvantages (speed, unnecessary objects created ... whatever). If this is possible only in C#: Never mind! This makes me feel good to learn C# after coding some basic stuff in VB for some weeks.

In another thread b1xml2 explained:

"By using the EventList object found within the ComponentModel and applicable to WinForms, WebForms. UserControls, you create one instance of the event per class. This optimises the event handling."

So is the "BurntSky" - method equal in this respect?

And... @BurntSky: In your example Class1 would be my custom control class and Class2 my main Form class , right?


I am just placing all these questions, because I have the impression that I have the chance to talk to two real experts and I consider good understanding of delegates and event handling as one of the core topics to learn. And good knowledge here will most likely safe me a lot of headache later...


So if you feel that you've done your work, let me know and we can open another thread with fresh points...


0
 

Author Comment

by:i-Thomas
ID: 14022558
@b1xml2:

   OnClosePanel(new ClosePanelEventArgs(10));

This line causes an error (try to translate): "No overloading for the method OnClosePanel requires '1' arguments" ...
0
 
LVL 9

Expert Comment

by:BurntSky
ID: 14022733
If you're still deciding between learning VB.NET and C#, I really have to recommend C#.  It is true that a lot of the stuff you can do in both languages, but it's the little differences that really make C# the better choice (things like operator overloading, ternary sequences, unmanaged code, etc.).  Not to mention that C# is an obvious choice if you're looking for a career.  Browse around Monster.com and you'll see that ~90% of employers seeking .NET programmers want C# experience.

I've never heard about b1xml2's claim that the eventlist optimizes performance, but that doesn't mean it's not true.  I was under the understanding that the field like declaration of an event (my way: "public event EventHandler EventName") was compiled into the property-like declaration anyway; just that C# doesn't require you to write all the extra code.

Yes, Class1 is your control (the class that exposes the event) and Class2 is your form (the class that handles the event).

Feel free to ask questions pertaining to this particular topic in this thread.  If you have other unrelated questions, please open a new thread.  Opening a new thread will also expose it to more people who may have different solutions than I have.

Also, the reason that line is throwing an error is because your definition of the OnClosePanel() method probably doesn't accept a parameter.
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 14023472
 OnClosePanel(new ClosePanelEventArgs(this,10));
0
 
LVL 23

Accepted Solution

by:
b1xml2 earned 1200 total points
ID: 14024146
forget the previous submission.

look again at the code provided:

 private static readonly object ClosePanelEvent = new object();

        public event ClosePanelEventHandler ClosePanel
        {
            add
            {
                this.Events.AddHandler(ClosePanelEvent, value);
            }
           
            remove
            {
                this.Events.RemoveHandler(ClosePanelEvent, value);
            }
        }


        private void OnClosePanel(ClosePanelEventArgs args)
        {
            ClosePanelEventHandler handler = this.Events[ClosePanelEvent] as ClosePanelEventHandler;
            if (handler != null)
            {
                handler(this,args);
            }
        }


       private void uxCloseBtn_Click(object sender, System.EventArgs e)    // this triggers the event
       {
          /// just adding a value to show you how to do it
            OnClosePanel(new ClosePanelEventArgs(10)); /// note
       }


public class ClosePanelEventArgs : EventArgs   // Definition of the event class
{
     public readonly int ID;
     
     
     public ClosePanelEventArgs(int ID)    
     {
          this.ID = ID;
     }
     
     
}
   
   
    public delegate void ClosePanelEventHandler(object sender,ClosePanelEventArgs args);
0
 

Author Comment

by:i-Thomas
ID: 14024798
For all:

I posted new thread for principal discussion of advantges / disadvantages of the suggested solutions:

http://www.experts-exchange.com/Programming/Programming_Languages/C_Sharp/Q_21427867.html


@b1xml2:

Now I got your solution running! Very nice feeling after all trying...

One question concerning the line

"OnClosePanel(new ClosePanelEventArgs(10));"

So instead of 10 I could insert any variable that contains index of item etc., right?

How do I get this value back from the event after subscribing to it? I don't know exactly how to insert handling "e" here properly to retrieve the value:

       private void Panel_Closed(object sender, ClosePanelEventArgs e)
        {
            // Convert the sender object to a specific object type.
            LightControlPanel panel = (LightControlPanel) sender;

            // Get the name of the panel.
            string name = panel.lightControlName;
            Debug.WriteLine("Panel " + name + " pressed");
        }


Thanks for answering! After this I will split points and close this topic!
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 14024848
>>
So instead of 10 I could insert any variable that contains index of item etc., right?
<<
yep!!
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 14024856
private void Panel_Closed(object sender, ClosePanelEventArgs e)
{
      // Convert the sender object to a specific object type.
      LightControlPanel panel = (LightControlPanel) sender;
      int value = e.ID;
      
      // Get the name of the panel.
      string name = panel.lightControlName;
      Debug.WriteLine("Panel " + name + " pressed");
}
0
 
LVL 23

Expert Comment

by:b1xml2
ID: 14024858
Because you can pass thru objects via classes that inherit from the EventArgs class (the 2nd parameter), all events do not therefore need to return any value.
0
 

Author Comment

by:i-Thomas
ID: 14025055
OK, b1xml2, many many thanks for your quick helping and sharing your (obviously quite special) knowledge about proper event handling. I will practice now and try to use this as much as possible.

@BurntSky: Thank you very much, too, for bringing in another way to handle events that I will use for sure when it is not about custom controls.

My suggestion is to split points:

300 for b1xml2
200 for BurntSky

ok?

0
 
LVL 23

Expert Comment

by:b1xml2
ID: 14025102
it's alright with me =)
0
 
LVL 9

Expert Comment

by:BurntSky
ID: 14025107
Fine with me as well.
0
 

Author Comment

by:i-Thomas
ID: 14025145
Ok. Accepted.

Thanks once more.

BTW:

If you think I can improve my "ee-behaviour" e.g. clearer problem description etc., please let me know!

I highly admire all the help I received from ee very much and as I will not be able to answer many questions with my current knowledge-level the minimum I can give back to ee is to make my threads as useful to others as possible!

One problem I encounter from time to time is that only after some help and discussions in the thread I know the real name of the problem, because I did not have enough knowledge to pinpoint the problem...
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
There may be issues when you are trying to access Outlook or send & receive emails or due to Outlook crash which leads to corrupt or damaged PST file. To eliminate the corruption from your PST file, you need to repair the corrupt Outlook PST file. U…
Get the source code for a fully functional Access application shell with several popular security features that Access VBA application developers desire, but find difficult or impossible to figure out how to code. You get the source code for managi…
Suggested Courses

612 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question