Back to Devexpress

Custom Nodes

windowsforms-5597-controls-and-libraries-tree-list-feature-center-nodes-custom-nodes.md

latest9.4 KB
Original Source

Custom Nodes

  • Nov 14, 2022
  • 5 minutes to read

Custom nodes, which are TreeListNode descendants, allow you to extend the default node capabilities. This topic shows how to create custom nodes and use them in a Tree List control.

Custom Nodes

Nodes of the Tree List control (TreeListNode objects) are not created directly. The Tree List control doesn’t call the TreeListNode constructor. Instead, it calls the protected CreateNode method each time a new node needs to be created. This method has the following syntax:

protected virtual TreeListNode CreateNode(int nodeID, TreeListNodes owner);

This method must return the newly created node. The nodeID and owner parameters specify the node’s identifier and the owning collection. The first parameter corresponds to the TreeListNode.Id property. The second parameter is the parent node’s TreeListNode.Nodes property value. (If a root level node is created, the owner parameter is equal to the TreeList.Nodes property value.)

The following technique allows you to create custom nodes:

  • Create a TreeListNode descendant with the required functionality.
  • Create a TreeList control descendant, and override the CreateNode method, to return a newly created node of a custom type.
  • Add the derived control to the form.

Example

This example shows how to create a custom node class that introduces a Height property. This property will allow heights to be set for individual nodes.

csharp
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustomTreeList_NodeHeight {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();

            List<MyRecord> list = new List<MyRecord>();
            list.Add(new MyRecord(0, -1, "Corporate Headquarters", 1000000, "Monterey"));
            list.Add(new MyRecord(1, 0, "Sales and Marketing", 22000, "San Francisco"));
            list.Add(new MyRecord(2, 0, "Finance", 40000, "Monterey"));
            list.Add(new MyRecord(3, 0, "Engineering", 1100000, "Monterey"));
            list.Add(new MyRecord(4, -1, "Customer Services", 850000, "Burlington, VT"));

            treeList1.DataSource = list;
            treeList1.Columns["Budget"].Format.FormatType = DevExpress.Utils.FormatType.Numeric;
            treeList1.Columns["Budget"].Format.FormatString = "c0";

        }

        private void Form1_Load(object sender, EventArgs e) {
            treeList1.ForceInitialize();
            treeList1.ExpandAll();
            ((MyTreeListNode)treeList1.Nodes[0]).Height = 35;
            ((MyTreeListNode)treeList1.Nodes[0].Nodes[1]).Height = 35;

        }
    }

    public class MyTreeList : TreeList {
        public MyTreeList() : base() {
            OptionsBehavior.AutoNodeHeight = false;
        }

        protected override TreeListNode CreateNode(int nodeID, TreeListNodes owner, object tag) {
            return new MyTreeListNode(nodeID, owner);
        }
        protected override void InternalNodeChanged(TreeListNode node, TreeListNodes nodes, NodeChangeTypeEnum changeType) {
            if (changeType == NodeChangeTypeEnum.User1)
                LayoutChanged();
            base.InternalNodeChanged(node, nodes, changeType);
        }
        protected override void RaiseCalcNodeHeight(TreeListNode node, ref int nodeHeight) {
            MyTreeListNode myNode = node as MyTreeListNode;
            if (myNode != null)
                nodeHeight = myNode.Height;
            else
                base.RaiseCalcNodeHeight(node, ref nodeHeight);
        }
        public virtual int DefaultNodesHeight { get { return 18; } }
    }
    public class MyTreeListNode : TreeListNode {
        const int minHeight = 5;
        int height;
        public MyTreeListNode(int id, TreeListNodes owner) : base(id, owner) {
            this.height = (owner.TreeList as MyTreeList).DefaultNodesHeight;
        }
        public int Height {
            get { return height; }
            set {
                if (Height == value || value < minHeight) return;
                height = value;
                Changed(NodeChangeTypeEnum.User1);
            }
        }
    }

    public class MyRecord {
        public int ID { get; set; }
        public int ParentID { get; set; }

        public string Department { get; set; }
        public string Location { get; set; }
        public decimal Budget { get; set; }

        public MyRecord(int id, int parentID, string department, decimal budget, string location) {
            ID = id;
            ParentID = parentID;
            Department = department;
            Budget = budget;
            Location = location;
        }
    }

}
vb
Imports DevExpress.XtraTreeList
Imports DevExpress.XtraTreeList.Nodes
Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows.Forms

Namespace CustomTreeList_NodeHeight
    Partial Public Class Form1
        Inherits Form

        Public Sub New()
            InitializeComponent()

            Dim list As New List(Of MyRecord)()
            list.Add(New MyRecord(0, -1, "Corporate Headquarters", 1000000, "Monterey"))
            list.Add(New MyRecord(1, 0, "Sales and Marketing", 22000, "San Francisco"))
            list.Add(New MyRecord(2, 0, "Finance", 40000, "Monterey"))
            list.Add(New MyRecord(3, 0, "Engineering", 1100000, "Monterey"))
            list.Add(New MyRecord(4, -1, "Customer Services", 850000, "Burlington, VT"))

            treeList1.DataSource = list
            treeList1.Columns("Budget").Format.FormatType = DevExpress.Utils.FormatType.Numeric
            treeList1.Columns("Budget").Format.FormatString = "c0"

        End Sub

        Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
            treeList1.ForceInitialize()
            treeList1.ExpandAll()
            CType(treeList1.Nodes(0), MyTreeListNode).Height = 35
            CType(treeList1.Nodes(0).Nodes(1), MyTreeListNode).Height = 35
        End Sub
    End Class

    Public Class MyTreeList
        Inherits TreeList
        Public Sub New()
            MyBase.New()
            OptionsBehavior.AutoNodeHeight = False
        End Sub

        Protected Overrides Function CreateNode(ByVal nodeID As Integer, ByVal owner As TreeListNodes, ByVal tag As Object) As TreeListNode
            Return New MyTreeListNode(nodeID, owner)
        End Function
        Protected Overrides Sub InternalNodeChanged(ByVal node As TreeListNode, ByVal nodes As TreeListNodes, ByVal changeType As NodeChangeTypeEnum)
            If changeType = NodeChangeTypeEnum.User1 Then
                LayoutChanged()
            End If
            MyBase.InternalNodeChanged(node, nodes, changeType)
        End Sub
        Protected Overrides Sub RaiseCalcNodeHeight(ByVal node As TreeListNode, ByRef nodeHeight As Integer)
            Dim myNode As MyTreeListNode = CType(node, MyTreeListNode)
            If Not myNode Is Nothing Then
                nodeHeight = myNode.Height
            Else
                MyBase.RaiseCalcNodeHeight(node, nodeHeight)
            End If
        End Sub
        Public Overridable ReadOnly Property DefaultNodesHeight() As Integer
            Get
                Return 18
            End Get
        End Property
    End Class

    Public Class MyTreeListNode
        Inherits TreeListNode
        Const minHeight As Integer = 5
        Dim fHeight As Integer
        Public Sub New(ByVal id As Integer, ByVal owner As TreeListNodes)
            MyBase.New(id, owner)
            Me.fHeight = CType(owner.TreeList, MyTreeList).DefaultNodesHeight
        End Sub
        Public Property Height() As Integer
            Get
                Return fHeight
            End Get
            Set(ByVal Value As Integer)
                If fHeight = Value Or Value < minHeight Then Return
                fHeight = Value
                Changed(NodeChangeTypeEnum.User1)
            End Set
        End Property
    End Class

    Public Class MyRecord
        Public Property ID() As Integer
        Public Property ParentID() As Integer

        Public Property Department() As String
        Public Property Location() As String
        Public Property Budget() As Decimal

        Public Sub New(ByVal id As Integer, ByVal parentID As Integer, ByVal department As String, ByVal budget As Decimal, ByVal location As String)
            Me.ID = id
            Me.ParentID = parentID
            Me.Department = department
            Me.Budget = budget
            Me.Location = location
        End Sub
    End Class

End Namespace