Pelle
Pelle

Reputation: 741

How to inherit from WPF control and use generic class at the same time in C#?

It starts out with a generic class and then I inherit from that one. Now I have a Node, which will be represented visually at a later stage. My plan was then to inherit from the Thumb control to allow my node to support dragging, but now the problem is that multiple inheritance is not supported in C#. So my only option at this point seems to be to just scrap my code and inherit the base class from Thumb (which I don't prefer due to my plan of having certain Node classes that does not support the functionality in the Thumb class). Is there no way for me to use my generic class and at the same time inherit functionality from the Thumb class (WPF)? It would be very nice to be able to inherit Node to create more specialized classes that could also support functionality from WPF controls like Thumb.

public class BaseNode<T> where T : BaseNode<T>
{
    private T _item;
    private T _parent;
    private List<BaseNode<T>> _children;

    public T Item
    {
        get { return _item; }
        set { _item = value; }
    }

    public BaseNode(T item)
    {
        _item = item;
    }
    public void SetParent(T parent)
    {
        _parent.Item = parent;
    }
    public void AddChild(T child)
    {
        _children.Add(new BaseNode<T>(child));
    }
    public void RemoveChild(T child)
    {
        var node = _children.FirstOrDefault(e => e.Item.Equals(child));
        if (node != null)
            _children.Remove(node);
    }
}

public class Node : BaseNode<Node>
{
    private Node _item;
    private List<NodeElement> NodeElements;

    Node (Node item) : base(item)
    {
        _item = item;
    }

    public void ResetElements()
    {
        NodeElements.ForEach(e => e.ResetState());
    }

    public void AddElement(NodeElement element)
    {
        NodeElements.Add(element);
    }

    public void RemoveElement(NodeElement element)
    {
        var elem = NodeElements.FirstOrDefault(e => e.Equals(element));
        if (elem != null)
            NodeElements.Remove(elem);
    }
}

Upvotes: 2

Views: 194

Answers (1)

mm8
mm8

Reputation: 169400

If you want to create a custom Thumb your class should inherit from Thumb. You can then use your generic class using composition. Something like this:

public interface INode<T>
{
    T Item { get; set; }
    void SetParent(T parent);
    void AddChild(T child);
    void RemoveChild(T child);
}

public class BaseNode<T> where T : INode<T>
{
    private T _item;
    private T _parent;
    private List<BaseNode<T>> _children;

    public T Item
    {
        get { return _item; }
        set { _item = value; }
    }

    public BaseNode(T item)
    {
        _item = item;
    }
    public void SetParent(T parent)
    {
        _parent.Item = parent;
    }
    public void AddChild(T child)
    {
        _children.Add(new BaseNode<T>(child));
    }
    public void RemoveChild(T child)
    {
        var node = _children.FirstOrDefault(e => e.Item.Equals(child));
        if (node != null)
            _children.Remove(node);
    }
}

public class Node : Thumb, INode<Node>
{
    private Node _item;
    private List<NodeElement> NodeElements;
    private readonly BaseNode<Node> _base;

    public Node()
    {
        _base = new BaseNode<Node>(this);
    }

    public void ResetElements()
    {
        NodeElements.ForEach(e => e.ResetState());
    }

    public void AddElement(NodeElement element)
    {
        NodeElements.Add(element);
    }

    public void RemoveElement(NodeElement element)
    {
        var elem = NodeElements.FirstOrDefault(e => e.Equals(element));
        if (elem != null)
            NodeElements.Remove(elem);
    }

    public Node Item
    {
        get { return _base.Item; }
        set { _base.Item = value; }
    }

    public void SetParent(Node parent)
    {
        _base.SetParent(parent);
    }
    public void AddChild(Node child)
    {
        _base.AddChild(child);
    }
    public void RemoveChild(Node child)
    {
        _base.RemoveChild(child);
    }
}

All nodes inclucing the custom control implements the INode<T> interface.

Upvotes: 2

Related Questions