D
Danny Tuppeny
Hi all,
I've been trying to write some classes, so when I have a parent-child
relationship, such as with Folders in my application, I don't have to
remember to add a parent reference, as well as adding to the child
collection, eg:
parent.Children.Add(child);
child.Parent = parent;
And I've come up with the below (I've included my test, and three classes).
It seems to work, but I have two questions....
1. Does this look like the best way of doing this?
2. I now want to extend this to support multiple lists (eg, my folders can
contain both folders, and messages. Messages can have child messages, and
therefore have both a parent folder, and a parent message), eg.
folder.ChildFolders // Returns List<TreeItem<Folder>>
folder.Messages // Returns List<TreeItem<Message>>
message.ParentMessage // Returns TreeItem<Message>
message.ParentFolder // Returns TreeItem<Folder>
Or should I create a base class that represents the entire tree (Folders and
Messages)? Though this way, I'd have a single child list, and would need to
add properties, like .ChildFolders, which would filter the .Children list!
I know it looks like a lot of code here, but it's just 3 classes and my
command line test. If you paste it into VS, it'll look dead simple
Any thoughts or suggestions?
Thanks,
Danny Tuppeny
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
Test1();
Test2();
}
static void Test1()
{
Folder parent = new Folder();
Folder child = new Folder();
child.Parent = parent;
if (parent.Children.Contains(child))
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
static void Test2()
{
Folder parent = new Folder();
Folder child = new Folder();
parent.Children.Add(child);
if (parent == child.Parent)
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
}
public class ChildList<T> : List<T>
{
public event EventHandler<ChildListEventArgs<T>> Added;
public event EventHandler<ChildListEventArgs<T>> Removed;
public class ChildListEventArgs<T> : EventArgs
{
public T Item;
public ChildListEventArgs(T item)
{
Item = item;
}
}
public new void Add(T item)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
added(this, new ChildListEventArgs<T>(item));
base.Add(item);
}
public new void AddRange(IEnumerable<T> collection)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
{
foreach (T item in collection)
{
added(this, new ChildListEventArgs<T>(item));
}
}
base.AddRange(collection);
}
public new void Insert(int index, T item)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
added(this, new ChildListEventArgs<T>(item));
base.Insert(index, item);
}
public new void InsertRange(int index, IEnumerable<T> collection)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
{
foreach (T item in collection)
{
added(this, new ChildListEventArgs<T>(item));
}
}
base.InsertRange(index, collection);
}
public new bool Remove(T item)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
removed(this, new ChildListEventArgs<T>(item));
return base.Remove(item);
}
public new void RemoveAll(Predicate<T> match)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
{
foreach (T item in base.FindAll(match))
{
removed(this, new ChildListEventArgs<T>(item));
}
}
base.RemoveAll(match);
}
public new void RemoveAt(int index)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
removed(this, new ChildListEventArgs<T>(base[index]));
base.RemoveAt(index);
}
new void RemoveRange(int index, int count)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
{
foreach (T item in base.GetRange(index, count))
{
removed(this, new ChildListEventArgs<T>(item));
}
}
base.RemoveAt(index);
}
}
public class TreeItem<T>
{
TreeItem<T> parent;
ChildList<TreeItem<T>> children;
public TreeItem()
{
children = new ChildList<TreeItem<T>>();
children.Added += delegate(object sender,
ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem<T>> e) { e.Item.parent =
this; };
children.Removed += delegate(object sender,
ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem<T>> e) { e.Item.parent =
null; };
}
public TreeItem<T> Parent
{
get { return parent; }
set
{
if (parent != value)
{
if (parent != null)
{
// This automagically unsets the internal parent
parent.children.Remove(this);
}
if (value != null)
{
// This automagically sets the internal parent
value.children.Add(this);
}
}
}
}
public ChildList<TreeItem<T>> Children
{
get { return children; }
}
}
public class Folder : TreeItem<Folder>
{
string name;
public Folder()
{
}
public string Name
{
get { return name; }
set { name = value; }
}
}
}
I've been trying to write some classes, so when I have a parent-child
relationship, such as with Folders in my application, I don't have to
remember to add a parent reference, as well as adding to the child
collection, eg:
parent.Children.Add(child);
child.Parent = parent;
And I've come up with the below (I've included my test, and three classes).
It seems to work, but I have two questions....
1. Does this look like the best way of doing this?
2. I now want to extend this to support multiple lists (eg, my folders can
contain both folders, and messages. Messages can have child messages, and
therefore have both a parent folder, and a parent message), eg.
folder.ChildFolders // Returns List<TreeItem<Folder>>
folder.Messages // Returns List<TreeItem<Message>>
message.ParentMessage // Returns TreeItem<Message>
message.ParentFolder // Returns TreeItem<Folder>
Or should I create a base class that represents the entire tree (Folders and
Messages)? Though this way, I'd have a single child list, and would need to
add properties, like .ChildFolders, which would filter the .Children list!
I know it looks like a lot of code here, but it's just 3 classes and my
command line test. If you paste it into VS, it'll look dead simple
Any thoughts or suggestions?
Thanks,
Danny Tuppeny
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
Test1();
Test2();
}
static void Test1()
{
Folder parent = new Folder();
Folder child = new Folder();
child.Parent = parent;
if (parent.Children.Contains(child))
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
static void Test2()
{
Folder parent = new Folder();
Folder child = new Folder();
parent.Children.Add(child);
if (parent == child.Parent)
{
Console.WriteLine("Test succeeded");
}
else
{
Console.WriteLine("Test failed");
}
}
}
public class ChildList<T> : List<T>
{
public event EventHandler<ChildListEventArgs<T>> Added;
public event EventHandler<ChildListEventArgs<T>> Removed;
public class ChildListEventArgs<T> : EventArgs
{
public T Item;
public ChildListEventArgs(T item)
{
Item = item;
}
}
public new void Add(T item)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
added(this, new ChildListEventArgs<T>(item));
base.Add(item);
}
public new void AddRange(IEnumerable<T> collection)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
{
foreach (T item in collection)
{
added(this, new ChildListEventArgs<T>(item));
}
}
base.AddRange(collection);
}
public new void Insert(int index, T item)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
added(this, new ChildListEventArgs<T>(item));
base.Insert(index, item);
}
public new void InsertRange(int index, IEnumerable<T> collection)
{
EventHandler<ChildListEventArgs<T>> added = Added;
if (added != null)
{
foreach (T item in collection)
{
added(this, new ChildListEventArgs<T>(item));
}
}
base.InsertRange(index, collection);
}
public new bool Remove(T item)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
removed(this, new ChildListEventArgs<T>(item));
return base.Remove(item);
}
public new void RemoveAll(Predicate<T> match)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
{
foreach (T item in base.FindAll(match))
{
removed(this, new ChildListEventArgs<T>(item));
}
}
base.RemoveAll(match);
}
public new void RemoveAt(int index)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
removed(this, new ChildListEventArgs<T>(base[index]));
base.RemoveAt(index);
}
new void RemoveRange(int index, int count)
{
EventHandler<ChildListEventArgs<T>> removed = Removed;
if (removed != null)
{
foreach (T item in base.GetRange(index, count))
{
removed(this, new ChildListEventArgs<T>(item));
}
}
base.RemoveAt(index);
}
}
public class TreeItem<T>
{
TreeItem<T> parent;
ChildList<TreeItem<T>> children;
public TreeItem()
{
children = new ChildList<TreeItem<T>>();
children.Added += delegate(object sender,
ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem<T>> e) { e.Item.parent =
this; };
children.Removed += delegate(object sender,
ChildList<TreeItem<T>>.ChildListEventArgs<TreeItem<T>> e) { e.Item.parent =
null; };
}
public TreeItem<T> Parent
{
get { return parent; }
set
{
if (parent != value)
{
if (parent != null)
{
// This automagically unsets the internal parent
parent.children.Remove(this);
}
if (value != null)
{
// This automagically sets the internal parent
value.children.Add(this);
}
}
}
}
public ChildList<TreeItem<T>> Children
{
get { return children; }
}
}
public class Folder : TreeItem<Folder>
{
string name;
public Folder()
{
}
public string Name
{
get { return name; }
set { name = value; }
}
}
}