I have one collection of objects that many of my forms (using WeifenLuo.WinFormsUI.Docking) need to interact with.
i.e. If the collection has an addition (or deletion) made in one form, then the other forms respond by refreshing their views.
Obviously, an observer pattern would be a good candidate here. However, I am having issues trying to implement this in my program.
First, it seemed best to create an observer class for my collection like so:
public class DataCollectionObserver : Form
{
internal static void DataCollectionRegister(DataCollection dataCollection)
{
dataCollection.ImageAdded += new EventHandler(dataAdded);
dataCollection.ImageRemoved += new EventHandler(dataRemoved);
dataCollection.ImageIndexChanged += new EventHandler(dataIndexChanged);
dataCollection.ImageListCleared += new EventHandler(dataListCleared);
}
internal static void DataCollectionUnRegister(DataCollection dataCollection)
{
dataCollection.ImageAdded -= new EventHandler(dataAdded);
dataCollection.ImageRemoved -= new EventHandler(dataRemoved);
dataCollection.ImageIndexChanged -= new EventHandler(dataIndexChanged);
dataCollection.ImageListCleared -= new EventHandler(dataListCleared);
}
internal static void dataAdded(object sender, EventArgs e) {}
internal static void dataRemoved(object sender, EventArgs e) {}
internal static void dataIndexChanged(object sender, EventArgs e) {}
internal static void dataListCleared(object sender, EventArgs e) {}
}
Then override the base event handlers in the subclassed forms?
But, I cannot do this and use the WeifenLuo.WinFormsUI.Docking library...
Well, I could have DataCollectionObserver inherit DockContent from WeifenLuo.WinFormsUI.Docking, but that creates a situation where I need to have two DataCollectionObserver classes - one which inherits Form and another that inherits DockContent :-[ or, I could make the DataCollectionObserver an Interface, but that still leaves me with duplicate code laying about...
So, does anyone have a suggestion here? Am I missing something obvious, or is this a situation where duplication of code 'must be done' for the sake of simplicity?
TIA
Edit://
I am not having problems getting notification in my forms. As a matter of fact, the whole thing is working right now. The reason that I am asking is because the whole thing "smells" due to the block copy and paste of code in these four different forms that I have which subscribe to the collection events and unsubscribe on Form.Closing().
What I would like to do is implement the behavior that I have copied and pasted to these four forms in one place and have the forms that should receive collection change notifications implement that behavior as needed.
Hope that makes things clearer?
FWIW, this is my collection class:
using System;
using System.Collections;
using System.Reflection;
namespace MyNameSpace.Collections
{
/// <summary>
/// Generic Collection of Objects with Events
/// </summary>
public class CollectionWithEvents<T> : CollectionBase
{
public bool SuppressEventNotification
{
get;
set;
}
public CollectionWithEvents()
{
SuppressEventNotification = false;
}
#region Events
/// <summary>
/// Raises before an item is added to the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> BeforeItemAdded;
/// <summary>
/// Raises when an item is added to the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> ItemAdded;
/// <summary>
/// Raises before a collection of items is added to the list.
/// </summary>
public event EventHandler<ItemsEventArgs<T>> BeforeItemsAdded;
/// <summary>
/// Raises when a collection of items is added to the list.
/// </summary>
public event EventHandler<ItemsEventArgs<T>> ItemsAdded;
/// <summary>
/// Raises before an item is changed in the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> BeforeItemChanged;
/// <summary>
/// Raises when an item is changed in the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> ItemChanged;
/// <summary>
/// Raises before an item is removed from the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> BeforeItemRemoved;
/// <summary>
/// Raises when an item is removed from the list.
/// </summary>
public event EventHandler<ItemEventArgs<T>> ItemRemoved;
/// <summary>
/// Raises when the items are cleared from the list.
/// </summary>
public event EventHandler<EventArgs> ItemsCleared;
#endregion
public T this[int index]
{
get { return (T)this.List[index]; }
set
{
if (!SuppressEventNotification)
{
OnBeforeItemChanged(this, new ItemEventArgs<T>(value));
}
this.List[index] = value;
if (!SuppressEventNotification)
{
OnItemChanged(this, new ItemEventArgs<T>(value));
}
}
}
public int Add(T item)
{
if (!SuppressEventNotification)
{
OnBeforeItemAdded(this, new ItemEventArgs<T>(item));
}
int retValue = this.List.Add(item);
if (!SuppressEventNotification)
{
OnItemAdded(this, new ItemEventArgs<T>(item));
}
return retValue;
}
public void AddRange(Collection<T> collection)
{
T[] tmp = new T[collection.Count];
collection.CopyTo(tmp, 0);
AddRange(tmp);
}
public void AddRange(T[] collection)
{
if (!SuppressEventNotification)
{
OnBeforeItemsAdded(this, new ItemsEventArgs<T>(collection));
}
this.AddRange(collection);
if (!SuppressEventNotification)
{
OnItemsAdded(this, new ItemsEventArgs<T>(collection));
}
}
public bool Contains(T item)
{
return this.List.Contains(item);
}
public void CopyTo(Array array, int index)
{
this.List.CopyTo(array, index);
}
public int IndexOf(T item)
{
return this.List.IndexOf(item);
}
public void Insert(int index, T item)
{
this.List.Insert(index, item);
}
public void Remove(T item)
{
if (!SuppressEventNotification)
{
OnBeforeItemRemoved(this, new ItemEventArgs<T>(item));
}
T tmp = (T)item;
this.List.Remove(item);
if (!SuppressEventNotification)
{
OnItemRemoved(this, new ItemEventArgs<T>(tmp));
}
tmp = default(T);
}
public void Sort(string Property, Common.SortOrder Order)
{
Common.GenericComparer genericComparer = new Common.GenericComparer(Property, Order);
this.InnerList.Sort(genericComparer);
}
#region Event Methods
/// <summary>
/// Raised before an Item is added to the list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnBeforeItemAdded(object sender, ItemEventArgs<T> e)
{
if (BeforeItemAdded != null)
{
BeforeItemAdded(sender, e);
}
}
/// <summary>
/// Raised when an Item is added to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnItemAdded(object sender, ItemEventArgs<T> e)
{
if (ItemAdded != null)
{
ItemAdded(sender, e);
}
}
/// <summary>
/// Raised before a collection of Items is added to the list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnBeforeItemsAdded(object sender, ItemsEventArgs<T> e)
{
if (BeforeItemsAdded != null)
{
BeforeItemsAdded(sender, e);
}
}
/// <summary>
/// Raised when a collection of Items is added to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnItemsAdded(object sender, ItemsEventArgs<T> e)
{
if (ItemsAdded != null)
{
ItemsAdded(sender, e);
}
}
/// <summary>
/// Raised before an Item is changed to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">GenericItemEventArgs</param>
protected virtual void OnBeforeItemChanged(object sender, ItemEventArgs<T> e)
{
if (BeforeItemChanged != null)
{
BeforeItemChanged(sender, e);
}
}
/// <summary>
/// Raised when an Item is changed to the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnItemChanged(object sender, ItemEventArgs<T> e)
{
if (ItemChanged != null)
{
ItemChanged(sender, e);
}
}
/// <summary>
/// Raised before an Item is removed from the list.
/// </summary>
/// <param name="sender"></param>
/// <param name="e">ItemEventArgs</param>
protected virtual void OnBeforeItemRemoved(object sender, ItemEventArgs<T> e)
{
if (BeforeItemRemoved != null)
{
BeforeItemRemoved(sender, e);
}
}
/// <summary>
/// Raised when an Item is removed from the list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">ItemEventsArgs</param>
protected virtual void OnItemRemoved(object sender, ItemEventArgs<T> e)
{
if (ItemRemoved != null)
{
ItemRemoved(sender, e);
}
}
/// <summary>
/// Raised when the Items are cleared from this list.
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">EventArgs</param>
protected virtual void OnItemsCleared(object sender, EventArgs e)
{
if (ItemsCleared != null)
{
ItemsCleared(sender, e);
}
}
#endregion
}
public class ItemEventArgs<T> : EventArgs
{
/// <summary>
/// Item
/// </summary>
public T Item { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="Item"></param>
public ItemEventArgs(T Item)
{
this.Item = Item;
}
}
public class ItemsEventArgs<T> : EventArgs
{
/// <summary>
/// Items
/// </summary>
public T[] Items { get; private set; }
/// <summary>
/// Default constructor
/// </summary>
/// <param name="Items"></param>
public ItemsEventArgs(T[] Items)
{
this.Items = Items;
}
}
}