Click here to Skip to main content
15,893,161 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
This seems so intuitive that I feel like I must be missing something obvious... Anyways, this is the first time I've tried to create events in a base class, so I don't know.
In the ListBox class I want to add a handler to the clicked event which can be found in the Control class (see the AddNewListBoxItem() method in ListBox). The handler should "select" the ListBoxItem, so that it will be drawn highlighted. Both the Listbox and the ListBoxItem inherit from Control class.

Although, the event fires in the base class (Control), the event is null, so the subscriber(ListBox) never gets the news.

Also, I apologize if my code is unprofessional or hard to read, I'm just a hobbyist; your recommendations and critiques regarding my practices are welcome also welcome.

I tried to post all of the code, but a dialog box warned me about your wrath, so the code can also be found here -> GitHub - MayhemusMaximus/MapEditor: An XNA Solution to Map Editing[^]

Control Class:
C#
public delegate void Clicked(object sender, EventArgs e);
public event Clicked clicked;
public virtual void OnClicked(EventArgs e)
{
    if (clicked != null)
        clicked(this.child, e);
}


private void handleMouseButtonEvents()
{
    if (mouseIsOver)
    {
        if(Statics.PreviousMouseState.LeftButton == ButtonState.Pressed
            && Statics.CurrentMouseState.LeftButton == ButtonState.Released)
            OnClicked(EventArgs.Empty);
    }
}


ListBox Class:
C#
namespace MapEditor.Controls
{
    public class ListBox : Control
    {
     ...


        public void AddNewListBoxItem(Texture2D texture, string text, Color imageColor)
        {
        ...

            ListBoxItem listBoxItem = new ListBoxItem(image, label);

            listBoxItem.clicked += listBoxItem_clicked;

            this.ListBoxItems.Add(listBoxItem);

        }

        void listBoxItem_clicked(object sender, EventArgs e)
        {
            foreach(ListBoxItem listBoxItem in ListBoxItems)
            {
                if (listBoxItem.IsSelected)
                    listBoxItem.IsSelected = false;
            }

            ((ListBoxItem)sender).IsSelected = true;
        }

    }
}


What I have tried:

I have rewritten this from scratch a couple of times, moved the subscription around within the method, searching Google, and asking I.T. staff at my work.
Posted
Updated 19-Mar-16 5:58am
v2
Comments
Sergey Alexandrovich Kryukov 18-Mar-16 18:43pm    
It looks like your event is really subscribed in your ListBox class to a list item. You can use the debugger to run the handler itself.

To start with, better follow the recommended form of event declaration. Define a class derived from System.EventArgs (or use EvenArgs itself). The the declaration should be:
public event System.EventHandler<MyEventArgs> myEventInstance;
or
public event System.EventHandler myEventInstance; // for underived EventArgs

By the way, it's pretty bad to expose the function invoking the event as public; it majorly defeat the purpose of events and the additional protection provided by them; you could use just "regular" delegates with the same success, but it's better to use events. An event instance cannot be invoked anywhere except the declaring class (not even in derived classed, nowhere else). This limitation should be considered as an important fool-proof feature, not as a hassle which you overcome through this public method (OnClicked)... Yes, in .NET FCL they do such things, but such parts are not the best parts of FCL...

—SA

See if this gives you some ideas:
C#
using System;

namespace YourNameSpace
{
    public class EventClassBase
    {
        public Action<string> Notify;
    }

    public class EventClassInheritor : EventClassBase
    {
        public void TriggerEvent(string str)
        {
            if (Notify != null) Notify(str);
        }
    }
}
Example of use: insert code inside a method or EventHandler in the same NameSpace:
C#
EventClassInheritor einh = new EventClassInheritor();

einh.Notify = s => { MessageBox.Show(s); }; 
           
einh.TriggerEvent("example of event call");
Keep in mind that the .NET 'Action is a full-featured delegate (some would regard it as "semantic sugar" around a delegate core; I find it very tasty).
 
Share this answer
 
v2
First of all, much thanks to Sergey Alexandrovich Kryukov and BillWoodruff. I have changed the access modifiers as suggested, and I am researching both deriving from EventArgs, and using Action.

The code failed to execute the way I intended because I never called the code that tests the criteria that need to be met to fire the event. I was trying something new to me with the event, so my only thought is that I wasn't doing it right. I overlooked the easiest bug of all...
 
Share this answer
 
Comments
BillWoodruff 19-Mar-16 13:53pm    
I'm glad you were assisted to find what you needed. I would consider creating a custom EventArgs sub-class only when I needed to pass back a range of different types of values when the event is triggered.

You can use Action with up to seventeen parameters to pass information (see the docs). In the case you want to not only notify some "consumer" of your event, but return a value to where the Event is called from, consider using Func (see the docs).

By using a Func on Form2 like public Func<int,int,bool> I can pass two numbers to external consumers of the event, and they will return a value (a bool in this case) back.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900