Generic Collections with Events?

Hi,

I am trying to make a tabbed control of my own. It's for a text editor and since the default one doesn't have the close button or a nice litle overflow menu like mine does now, I needed to make my own.

I have an implementation now, but I am not very happy with it. What I would love to be able to do is have something like the default TabbedControl, where you can do mTabControl.TabPages.Add(key, tabpage);

I am trying to use Generics so I dont have to do casts every 2 seconds, but the Dictionary<> class does not have any events. Can someone point me in the right direction here

Cheers,
Aditya


Answer this question

Generic Collections with Events?

  • Bhushan Akole

    You'll have to create your own dictionary class, and you can't simply override Dictionary either because its methods aren't marked as virtual.  That is, iInvoking Add on your class would fire an event but invoking Add on the base class would not.

    So your options are to either replicate the entire Dictionary class and forward all method calls to a Dictionary that you keep as a private field, or else override System.Collections.DictionaryBase... but that one is not generic, unfortunately.

    You might want to look at the Power Collections project, located here: http://www.wintellect.com/powercollections/. They might have a generic dictionary base class that you can extend. Be sure to look at their license, though -- it's a fairly nasty "shared source" license, not the usual LPGL/MIT license.


  • Charles W

    I am not really casting anything.

    This is the basic structure:

    class MyTabControl{

        public Dictionary<string, MyTabPage> TabPages;  

    }

    I want to be able to do MyTabControl.TabPages.Add(tabPage). This I can do right now, but I want the Dictionary<> to fire an event when an item is added to it. Is this possible Without overriding the Dictionary<> class I mean.

    IF overriding the Dictionary<> class is my only option, is there a way I can override it and still keep it generic For example, can I make a DictionaryWithEvents<> class that inherits from Dictionary<>

    Cheers,
    Aditya

  • Mr Big

    Sorry, I'm not sure I understand... Can you include some of the code where you are casting

    Thanks.

  • MrDewMan

    I believe this is the reason things like interfaces exist.

    Use them where appropriate and you shouldn't have any problems.  You'll notice a lot of .NET's CLR request the use of IList or ICollection or generics of those respectively.

    Myself I found I had to create my own implementation and associate it with an internal version of the object I wished to override.  Since it, in itself only derives from interfaces, you shouldn't have any difficulties with accurately manipulating the new Class to suit your needs.

    You can't hide the .Add member on interfaces, but on interfaces you can make sure that all add references go directly to you.

    For example:

    public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback

    As you can see, that's pretty much a copy of the Dictionary Generic class but with the custom name instead.  I needed a way to expose a type-safe type-indexed collection of objects that only I could alter, it accepts the same constructors as a normal Dictionary, and passes it on to a protected dictionary copy.  Relatively simple in concept.

    In my case:

    void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
    {
        throw new NotSupportedException("This method or operation is not supported");
    }


  • kingdech

    I dont know if my question wasn't as clear and maybe this is general knowledge already but this is what I wanted to do. I finally figured out how to extend generics:

    The following is my little test class. You have to make a dummy function for each operation you want events for and just call the base class and trigger an event. This seems to work fine. If anyone else is interested that is...



    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace EventGenerics
    {
        public class EList<T> : List<T>
        {

            public event System.EventHandler AddedItem;

            public new void Add(T item)
            {
                base.Add(item);
                if (AddedItem != null)
                {
                    AddedItem(this, new EventArgs());
                }
            }
        }
    }

     


    Cheers,
    Aditya

  • Blainy

    I was just not used to the concept of generics. Was sort of confused as to what would go in the <> when you extend a base generic or implement an interface.

    Thanks for all the help =)

    -Aditya

  • t0x1

    The problem with your approach is that the Add override isn't polymorphic. That means accessing your EList as a regular List (the base class) will invoke List.Add rather than EList.Add, and your event won't get fired.
  • Generic Collections with Events?