Skip to content

NodeControlContainer

Flexible TreeView allows you to show any control inside a node by using NodeControlContainer node control.

Control container#

Every control that's displayed in the node control should be wrapped by the ControlContainer class instance, which will control the control's behavior inside the treeview.

Example

NodeControlContainer nc = new NodeControlContainer();
nc.AttachTo(tree);

// Create the control to show inside a node control.
Button b = new Button();
b.Text = "Test";

// Create the node.
NodeWithControl n = new NodeWithControl();
// Create the control wrapper.
n.Container = new ControlContainer(b);
n.AttachTo(tree);
Dim nc As New NodeControlContainer()
nc.AttachTo(tree)

' Create the control to show inside a node control.
Dim b As New Button()
b.Text = "Test"

' Create the node.
Dim n As New NodeWithControl()
' Create the control wrapper.
n.Container = New ControlContainer(b)
n.AttachTo(tree)

ControlContainer's core properties:

  • Name - container name. Used to identify the container in the node's containers list in the NodeContainers node property.
  • Node - node where this container will be displayed.
  • Control - control that will be displayed in the node.
  • SmoothUpdate - defines the control update strategy (see below).
  • Visibility - defines the attached control visibility.
  • VisibilityManager - control containers visibility manager. Used to control many control containers' visibility from one point.

Multiple controls in the node#

You can display any number of controls inside each node.

To do that, you need to:

  • Inherit a node class from the ARMSoft.FlexibleTreeView.Node class where you can add as many members with the ControlContainer type as many controls inside every node you need.
  • Add to the treeview one NodeControlContainer node control for every control you defined in the node class before.
  • For every node, create controls you need to display.
  • Create a node where your controls will be displayed.

Example

// 1. Custom node class with an additional control container.
//    We'll have two controls shown in the node (NodeWithControl class already has the Container property built-in).
public class MyNode : NodeWithControl
{
    private ControlContainer _listContainer;

    // Additional control container for second control to show.
    public ControlContainer ListContainer
    {
        get { return _listContainer; }
        set
        {
            _listContainer = value;
            // Register the container in the node where it will be displayed.
            if(value != null)
            {
                value.Node = this;
            }
        }
    }
}

// 2.1. Add the node control to show first control. The NodeControlContainer node control is bound to the built-in Container property by default.
NodeControlContainer nc = new NodeControlContainer();
nc.AttachTo(tree);

// 2.2. Add the node control with custom binding for second control.
NodeControlContainer nc2 = new NodeControlContainer();
nc2.DataFieldName = "ListContainer";
nc2.AttachTo(tree);

// 3.1. Create the control for first NodeControlContainer node control.
Button b = new Button();
b.Text = "Test";

// 3.2. Create the control for second NodeControlContainer node control.
ListBox lb = new ListBox();
lb.Items.AddRange(new string[] { "One", "Two", "Three" });

// 4. Create the node where all controls will be shown.
MyNode n = new MyNode();
// Attach two controls to this node.
n.Container = new ControlContainer(b);
n.ListContainer = new ControlContainer(lb);
// Add this node to the treeview.
n.AttachTo(tree);
' 1. Custom node class with an additional control container.
'    We'll have two controls shown in the node (NodeWithControl class already has the Container property built-in).
Public Class MyNode
    Inherits NodeWithControl
    Private _listContainer As ControlContainer
    ' Additional control container for second control to show.
    Public Property ListContainer() As ControlContainer
        Get
            Return _listContainer
        End Get
        Set
            _listContainer = value
            ' Register the container in the node where it will be displayed.
            If value IsNot Nothing Then
                value.Node = Me
            End If
        End Set
    End Property
End Class

' 2.1. Add the node control to show first control. The NodeControlContainer node control is bound to the built-in Container property by default.
Dim nc As New NodeControlContainer()
nc.AttachTo(tree)

' 2.2. Add the node control with custom binding for second control.
Dim nc2 As New NodeControlContainer()
nc2.DataFieldName = "ListContainer"
nc2.AttachTo(tree)

' 3.1. Create the control for first NodeControlContainer node control.
Dim b As New Button()
b.Text = "Test"

' 3.2. Create the control for second NodeControlContainer node control.
Dim lb As New ListBox()
lb.Items.AddRange(New String() {"One", "Two", "Three"})

' 4. Create the node where all controls will be shown.
Dim n As New MyNode()
' Attach two controls to this node.
n.Container = New ControlContainer(b)
n.ListContainer = New ControlContainer(lb)
' Add this node to the treeview.
n.AttachTo(tree)

Binding to a node#

Every ControlContainer has a name in the Name property. Every node has the ControlContainers property with all control containers, displayed within this node, with a container name as a key, so it can be used to access all control containers in run-time. Also, the ControlContainer.GetControlNode static method can be used to get a node where the specified control is shown.

In the example below, we'll add the checkbox and the button controls using two NodeControlContainer node controls and checkbox will control the button's Enabled property state.

Warning

Do not create a ControlContainer instance in the bound property's getter! It will lead to a run-time error because of circular update calls.

Example

// Custom node class with two control containers (NodeWithControl class already has the Container property built-in).
public class MyNode : NodeWithControl
{
    private ControlContainer _buttonContainer;

    // Declare the node container for second control to display in the node. First container is inherited from the base class.
    public ControlContainer ButtonContainer
    {
        get { return _buttonContainer; }
        set
        {
            _buttonContainer = value;
            if(value != null)
            {
                value.Node = this;
            }
        }
    }
}

// Create two node controls to display two controls.
NodeControlContainer nc = new NodeControlContainer();
nc.AttachTo(tree);
NodeControlContainer nc2 = new NodeControlContainer();
// Attach the second node control to the new property.
nc2.DataFieldName = "ButtonContainer";
nc2.AttachTo(tree);

// Create the node where controls will be displayed.
MyNode n = new MyNode();

// Create first attached control: checkbox.
CheckBox cb = new CheckBox();
cb.Text = "Allow run";
cb.Checked = true;
// Work with this control like with any other control.
cb.CheckedChanged += new EventHandler(cb_CheckedChanged);
// Attach node container to the destination node.
n.Container = new ControlContainer(cb);

// Create second attached control: button.
Button b = new Button();
b.Text = "Run";
// Attach the control container to the node.
n.ButtonContainer = new ControlContainer(b);
// Give a name to the button's container to access it in run-time later.
n.ButtonContainer.Name = "button";

// Add this node to the treeview.
n.AttachTo(tree);

// Checkbox's event handler.
void cb_CheckedChanged(object sender, EventArgs e)
{
    Node node;
    ControlContainer buttonContainer;
    Button btn;
    CheckBox cb;

    cb = (CheckBox) sender;
    // Get a node where this checkbox is displayed.
    node = ControlContainer.GetControlNode<MyNode>(cb);
    // Get a control container where the button is hosted using the container name.
    buttonContainer = node.ControlContainers["button"];
    // Get the attached button control instance.
    btn = (Button)buttonContainer.Control;
    // Change the button's enabled state according to the checkbox check state.
    btn.Enabled = cb.Checked;
}
' Custom node class with two control containers (NodeWithControl class already has the Container property built-in).
Public Class MyNode
    Inherits NodeWithControl
    Private _buttonContainer As ControlContainer

    ' Declare the node container for second control to display in the node. First container is inherited from the base class.
    Public Property ButtonContainer() As ControlContainer
        Get
            Return _buttonContainer
        End Get
        Set
            _buttonContainer = value
            If value IsNot Nothing Then
                value.Node = Me
            End If
        End Set
    End Property
End Class

' Create two node controls to display two controls.
Dim nc As New NodeControlContainer()
nc.AttachTo(tree)
Dim nc2 As New NodeControlContainer()
' Attach the second node control to the new property.
nc2.DataFieldName = "ButtonContainer"
nc2.AttachTo(tree)

' Create the node where controls will be displayed.
Dim n As New MyNode()

' Create first attached control: checkbox.
Dim cb As New CheckBox()
cb.Text = "Allow run"
cb.Checked = True
' Work with this control like with any other control.
AddHandler cb.CheckedChanged, AddressOf cb_CheckedChanged
' Attach node container to the destination node.
n.Container = New ControlContainer(cb)

' Create second attached control: button.
Dim b As New Button()
b.Text = "Run"
' Attach the control container to the node.
n.ButtonContainer = New ControlContainer(b)
' Give a name to the button's container to access it in run-time later.
n.ButtonContainer.Name = "button"

' Add this node to the treeview.
n.AttachTo(tree)

' Checkbox's event handler.
Private Sub cb_CheckedChanged(sender As Object, e As EventArgs)
    Dim node As Node
    Dim buttonContainer As ControlContainer
    Dim btn As Button
    Dim cb As CheckBox

    cb = DirectCast(sender, CheckBox)
    ' Get a node where this checkbox is displayed.
    node = ControlContainer.GetControlNode(Of MyNode)(cb)
    ' Get a control container where the button is hosted using the container name.
    buttonContainer = node.ControlContainers("button")
    ' Get the attached button control instance.
    btn = DirectCast(buttonContainer.Control, Button)
    ' Change the button's enabled state according to the checkbox check state.
    btn.Enabled = cb.Checked
End Sub

Control visibility and visibility manager#

ControlContainer allows you to easily control the control's visibility using the Visibility and VisibilityManager properties. The main difference between them is that the Visibility is used when you need to control the control's visibility separately from each other, while the VisibilityManager is used to control the visibility of many controls from one place.

Visibility#

The Visibility property is used when you need to control the control's visibility separately from each other. By default, every attached control is always visible; however, you can define a node state's combination and show the attached control only for nodes with these states or you can choose whether to show or hide that control for every node in any state separately.

The available visibility settings:

  • Never - never show an object in the node.
  • Always - always show an object in the node.
  • GeneralNode - show an object only for a general node that is not selected, not focused, not soft selected and not under the mouse cursor.
  • SelectedNode - show an object only in selected nodes.
  • FocusedNode - show an object only in a focused node.
  • HotNode - show an object only in a node under the mouse cursor.
  • SoftSelectedNode - show an object only in a soft selected node when the SoftSelection mode (tree.Options.Selection.HoverStyle=eHoverStyle.SoftSelect) is enabled.

Note

These visibility states may be combined to define the control's visibility for a particular node in different states.

For example, to show a control only for focused and hot nodes use this code:

// Create node controls to show the node title and a button control.
NodeTextBox tb = new NodeTextBox();
tb.AttachTo(tree);
NodeControlContainer nc = new NodeControlContainer();
nc.AttachTo(tree);

// Create a node where the control container will be displayed.
NodeWithControl n = new NodeWithControl("Test node");
Button b = new Button();
b.Text = "Test";
n.Container = new ControlContainer(b);
// Show the button control only for focused or hot (under the mouse cursor) nodes.
n.Container.Visibility = eObjectVisibility.FocusedNode | eObjectVisibility.HotNode;
n.AttachTo(tree);

// Enable the dynamic node height mode to recalculate node height when the button was shown or hidden.
tree.Options.Node.AutoNodeHeight = true;
' Create node controls to show the node title and a button control.
Dim tb As New NodeTextBox()
tb.AttachTo(tree)
Dim nc As New NodeControlContainer()
nc.AttachTo(tree)

' Create a node where the control container will be displayed.
Dim n As New NodeWithControl("Test node")
Dim b As New Button()
b.Text = "Test"
n.Container = New ControlContainer(b)
' Show the button control only for focused or hot (under the mouse cursor) nodes.
n.Container.Visibility = eObjectVisibility.FocusedNode Or eObjectVisibility.HotNode
n.AttachTo(tree)

' Enable the dynamic node height mode to recalculate node height when the button was shown or hidden.
tree.Options.Node.AutoNodeHeight = True

To hide a control container for a particular node, set the Visibility property to the eObjectVisibility.Never value.

VisibilityManager#

The VisibilityManager is used to control the visibility of many controls from one place. To do that, create the ObjectVisibilityManager class instance and set it for all control containers for which you want to control the visibility.

VisibilityManager properties:

  • Enabled - defines whether to use this manager when you get the object's visibility or to use the Visibility property instead.
  • Visibility - defines the control containers' visibility.

Example

// Create node controls.
NodeTextBox tb = new NodeTextBox();
tb.AttachTo(tree);
NodeControlContainer nc = new NodeControlContainer();
nc.AttachTo(tree);

// Create the visibility manager.
ObjectVisibilityManager visman = new ObjectVisibilityManager();
// Show controls only in a focused or hot node.
visman.Visibility = eObjectVisibility.FocusedNode | eObjectVisibility.HotNode;

// Add nodes.
NodeWithControl node = new NodeWithControl("Test node 1");
Button b = new Button();
b.Text = "Button 1";
node.Container = new ControlContainer(b);
node.Container.VisibilityManager = visman;
node.AttachTo(tree);

node = new NodeWithControl("Test node 2");
b = new Button();
b.Text = "Button 2";
node.Container = new ControlContainer(b);
node.Container.VisibilityManager = visman;
node.AttachTo(tree);

// Enable the node auto-height to recalculate node height when the button control has shown or hidden.
tree.Options.Node.AutoNodeHeight = true;
' Create node controls.
Dim tb As New NodeTextBox()
tb.AttachTo(tree)
Dim nc As New NodeControlContainer()
nc.AttachTo(tree)

' Create the visibility manager.
Dim visman As New ObjectVisibilityManager()
' Show controls only in a focused or hot node.
visman.Visibility = eObjectVisibility.FocusedNode Or eObjectVisibility.HotNode

' Add nodes.
Dim node As New NodeWithControl("Test node 1")
Dim b As New Button()
b.Text = "Button 1"
node.Container = New ControlContainer(b)
node.Container.VisibilityManager = visman
node.AttachTo(tree)

node = New NodeWithControl("Test node 2")
b = New Button()
b.Text = "Button 2"
node.Container = New ControlContainer(b)
node.Container.VisibilityManager = visman
node.AttachTo(tree)

' Enable the node auto-height to recalculate node height when the button control has shown or hidden.
tree.Options.Node.AutoNodeHeight = True

ControlContainer.SmoothUpdate#

When a custom control changes position, it will be updated by calling the Invalidate method. If the treeview has many visible controls, there may be a delay when redrawing those controls. To force a control to update, enable the SmoothUpdate control container property and the treeview will update controls using the Refresh method, which updates them immediately.