Flexible TreeView 5.1.9 Help
Data binding. Inspection

Validation

During binding of the data source all of the public properties (as columns and node controls) and objects (as nodes) located in the data source will be added to the treeview. Flexible TreeView will also let you perform a validation of these added to the treeview objects. In order to perform this task, turn on the Validate property of the DataBinding object and subscribe to the ColumnPopulatingNodeControlPopulating and NodePopulating events.


ColumnPopulating event

ColumnPopulating event allows validating or changing properties of added to the treeview columns which are formed out of the data source object properties. You can refuse to add such column in the event handler by setting value of the Cancel property to TRUE.

Example:

void tree_ColumnPopulating(FlexibleTreeView pTreeview, ColumnPopulatingEventArgs pArgs)
{
  if (pArgs.FieldName == "SomeField")
  {
    pArgs.Cancel = true;
  }
}
Private Sub tree_ColumnPopulating(pTreeview As FlexibleTreeView, pArgs As ColumnPopulatingEventArgs)
    If pArgs.FieldName = "SomeField" Then
        pArgs.Cancel = True
    End If
End Sub

Substitute auto-created column

While binding treeview to a data source it will create a separate treeview column for each bound visible data field. To change the auto-created column properties you could handle ColumnPopulating event, but it does not allow to replace the created column.

To substitute the auto-created column an ARMSoft.FlexibleTreeView.FlexibleTreeView class descendant should be created and its CreateBoundColumn method should be overridden as shown below.

class FlexibleTreeViewEx : FlexibleTreeView
{
  protected override TreeColumn CreateBoundColumn(string pBoundFieldName)
  {
    if(pBoundFieldName == "SpecialField")
    {
      TreeColumn column = new TreeColumn();
      column.Text = "Special field";
      column.Width = 200;
      return column;
    }
    return base.CreateBoundColumn(pBoundFieldName);
  }
}
Class FlexibleTreeViewEx
    Inherits FlexibleTreeView
    Protected Overrides Function CreateBoundColumn(pBoundFieldName As String) As TreeColumn
        If pBoundFieldName = "SpecialField" Then
            Dim column As New TreeColumn()
            column.Text = "Special field"
            column.Width = 200
            Return column
        End If
        Return MyBase.CreateBoundColumn(pBoundFieldName)
    End Function
End Class

After that, that new treeview type should be used instead ARMSoft.FlexibleTreeView.FlexibleTreeView on forms that needs custom columns.

 

NodeControlPopulating event

NodeControlPopulating event allows to validate the auto-created node controls which are formed out of the data source object properties. You can refuse to add such node control in the event handler by setting value of the Cancel property to TRUE as shown below.

void tree_NodeControlPopulating(FlexibleTreeView pTreeview, ARMSoft.FlexibleTreeView.Events.DataBinding.NodeControlPopulatingEventArgs pArgs)
{
  if(pArgs.FieldName == "HiddenField")
  {
    pArgs.Cancel = true;
  }
}
Private Sub tree_NodeControlPopulating(pTreeview As FlexibleTreeView, pArgs As ARMSoft.FlexibleTreeView.Events.DataBinding.NodeControlPopulatingEventArgs)
    If pArgs.FieldName = "HiddenField" Then
        pArgs.Cancel = True
    End If
End Sub

 

Substitute auto-created node control

When Flexible TreeView binds the new data source it automatically creates node control that is able to manage the bound data type. In case you need to inject a custom own node control that works with your data better you need to create a new treeview class that inherit ARMSoft.FlexibleTreeView.FlexibleTreeView type, override the CreateBoundNodeControl method and there create and return custom node control when needed.

Example:

private class CustomTreeview : FlexibleTreeView
{
  protected override BindableControl CreateBoundNodeControl(Type pNodeControlType, string pBoundFieldName, Type pBoundFieldType)
  {
    if (pBoundFieldName == "OrderTitle")
    {
      NodeTextBox customCtrl = new NodeTextBox();
      customCtrl.Style.Font = new Font(customCtrl.Style.Font, FontStyle.Bold);
      return customCtrl;
    }
  
    return base.CreateBoundNodeControl(pNodeControlType, pBoundFieldName, pBoundFieldType);
  }
}
Private Class CustomTreeview
    Inherits FlexibleTreeView
    Protected Overrides Function CreateBoundNodeControl(pNodeControlType As Type, pBoundFieldName As String, pBoundFieldType As Type) As BindableControl
        If pBoundFieldName = "OrderTitle" Then
            Dim customCtrl As New NodeTextBox()
            customCtrl.Style.Font = New Font(customCtrl.Style.Font, FontStyle.Bold)
            Return customCtrl
        End If
        Return MyBase.CreateBoundNodeControl(pNodeControlType, pBoundFieldName, pBoundFieldType)
    End Function
End Class

The sample above creates the custom node control (NodeTextBox, but you can create any node control) for the OrderTitle bound property and changes the font to display order titles in bold.

 

NodePopulating event

NodePopulating event allows to validate the added to the treeview nodes which are formed out of the data source objects. You can refuse to add such node in the event handler by setting value of the Cancel property to TRUE.

 

Substitute auto-created node

When Flexible TreeView binds the new data source it automatically creates the node that either holds the bound object's data or is linked to this data. In case you need to use a custom bindable node class in bound mode, you need to create a new treeview class that inherit ARMSoft.FlexibleTreeView.FlexibleTreeView type, override the CreateBoundNode method and return a custom node instance as show below.

The below example creates and returns the new bindable node class instance which converts the StringField column string value to integer on the fly.

Example:

class MyBindableNode : BindableNode
{
  public MyBindableNode(object pId) : base(pId)
  {
  }

  public override object GetBoundFieldValue(string pFieldName)
  {
    object value = base.GetBoundFieldValue(pFieldName);
    if(pFieldName == "StringField")
    {
      value = int.Parse((string)value);
    }
    return value;
  }
}

class FlexibleTreeViewEx : FlexibleTreeView
{
  protected override BindableNode CreateBoundNode(object id)
  {
    return new MyBindableNode(id);
  }
}
Class MyBindableNode
    Inherits BindableNode
    Public Sub New(pId As Object)
        MyBase.New(pId)
    End Sub

    Public Overrides Function GetBoundFieldValue(pFieldName As String) As Object
        Dim value As Object = MyBase.GetBoundFieldValue(pFieldName)
        If pFieldName = "StringField" Then
            value = Integer.Parse(DirectCast(value, String))
        End If
        Return value
    End Function
End Class


Class FlexibleTreeViewEx
    Inherits FlexibleTreeView
    Protected Overrides Function CreateBoundNode(id As Object) As BindableNode
        Return New MyBindableNode(id)
    End Function
End Class

 

Lazy load (load on demand)

By default, Flexible TreeView creates nodes for all of the objects in a data source. If you require a lazy load (in order to speed up loading of the data source) for any node, you can perform this task by subscribing to the NodePopulating event. In the event handler you need to cancel the process of adding to the tree view all of the nodes which have to be loaded later, by setting value of the Cancel parameter to TRUE, as well setting the LoadOnDemand to TRUE for all nodes, which children you need to load later.

Example:

void tree_NodePopulating(FlexibleTreeView pTreeview, NodePopulatingEventArgs pArgs)
{
  // for all nodes enable lazy load because we don't know whether this node has children.
  pArgs.Node.LoadOnDemand = true;
  
  // do not add all non-root nodes but load them later.
  if (pArgs.ParentNode != null)
  {
    pArgs.Cancel = true;
  }
}
 
// Lazy loading.
private void tree_NodeExpanding(FlexibleTreeView pTreeview, NodeExpandingEventArgs pArgs)
{
  // lazy load for the child node.
  if (pArgs.Node.LoadOnDemand)
  {
    // disable lazy load for the loaded nod.
    pArgs.Node.LoadOnDemand = false;
  
    // load node's children here...
  }
}
Private Sub tree_NodePopulating(pTreeview As FlexibleTreeView, pArgs As NodePopulatingEventArgs)
    ' for all nodes enable lazy load because we don't know whether this node has children.
    pArgs.Node.LoadOnDemand = True

    ' do not add all non-root nodes but load them later.
    If pArgs.ParentNode IsNot Nothing Then
        pArgs.Cancel = True
    End If
End Sub

' Lazy loading.
Private Sub tree_NodeExpanding(pTreeview As FlexibleTreeView, pArgs As NodeExpandingEventArgs)
    ' lazy load for the child node.
    If pArgs.Node.LoadOnDemand Then
        ' disable lazy load for the loaded nod.
        pArgs.Node.LoadOnDemand = False

        ' load node's children here...
    End If
End Sub

See below in order to find out how to add own nodes to the tree view with bound data source.

 

Add custom columns, node controls, nodes into a bound treeview

Many treeview controls after binding of the data source represent black-box and do not allow user any changes or additions. Flexible TreeView on the other hand, will allow you to fully customize the treeview even after binding of the data source in bound mode as well as in unbound mode.

 

Add column and node controls

If you need to add your own columns or node controls to the treeview, you can do that the same way as it was done before, by adding the TreeColumn instance in to the Columns property or NodeControl (or an inheritor) instance in to the NodeControls property.

 

Add node

Flexible TreeView works with bound data according to the binding mode - bound or unbound.
In bound mode Flexible TreeView stores only references to the bound objects and changes data directly. In unbound mode Flexible TreeView copies all of the fields of the bound object which needs to be shown.
Each node in a treeview, to which a data source is bound to, inherits from the BindableNode type, which allows an object to be bound to a data source as well as to store all of its fields.
Thus, the method of adding the node to a treeview will solely depend on binding type with a data source.

Further we will be using data source - list, including instances of some Order class:

class Order
{
  // class properties goes here
}
Class Order
  ' class properties goes here
End Class

Add node in bound mode

Let's assume that after binding of the data source we need to add one more object type Order in to the data source and in to a treeview. In order to perform this task let's create a new object and add it in to data source:

Order order = new Order();
// here ‘list' is our data source.
list.Add(order);   

// Then add a new object in to a tree view, by creating the BindableNode class instance and passing in to the constructor our new object of Order type.
BindableNode node = new BindableNode("object id here", order);
node.AttachTo(tree);
Dim order As New Order()
' here ‘list' is our data source.
list.Add(order)

' Then add a new object in to a tree view, by creating the BindableNode class instance and passing in to the constructor our new object of Order type.
Dim node As New BindableNode("object id here", order)
node.AttachTo(tree)           

Note, instead of "object id here" parameter above you need to pass a value of unique identifier of the new object. String type above was used only for example! You are free to use identifiers of any type.

That is it! New object is added to the treeview.

Note, you do not need to add new objects also in to your data source! All you need is to pass it into the node constructor.

 

Add node in unbound mode

In unbound mode situation is the same as in bound mode, but creating of the node should be done by using other constructor, where you should pass a Dictionary<string, object>, which have to include names of the properties showing in the tree view and their values:

// We can acquire list of the properties and their values by using the DataSourceManager class.
Dictionary<string, object> fieldValues = DataSourceManager.Current.GetFieldValues(order);
 
// Create and add a new node.
BindableNode node = new BindableNode("object id here", fieldValues);
node.AttachTo(tree);
' We can acquire list of the properties and their values by using the DataSourceManager class.
Dim fieldValues As Dictionary(Of String, Object) = DataSourceManager.Current.GetFieldValues(order)

' Create and add a new node.
Dim node As New BindableNode("object id here", fieldValues)
node.AttachTo(tree) 

Note, instead of "object id here" parameter above you need to pass a value of unique identifier of the new object. String type above was used only for example! You are free to use identifiers of any type.

Also note, all of changes made by user in to the treeview will not be shown in your object if it is done in the unbound mode.

If you need to add nodes, which will be bound with instances not of the Order type, you can do that, by following instructions above, while using instance of your type, but your data type have to have same properties as Order type.

 

Add node without linked object

You can also add to the treeview a virtual object, supplying needed date yourself without creation of the instance. In order to do that you need to inherit a class from BindableNode and override the GetBoundFieldValueSetBoundFieldValue and GetBoundFieldType methods as shown bellow.

// Custom node class that holds the bound value inside.
class VirtualBindableNode : BindableNode
{
  private string _userNameValue = "John Smith";  // data initial value.

  protected override Type GetBoundFieldType(string pFieldName)
  {
    if(pFieldName == "UserName")
    {
      return typeof(string);
    }
    return base.GetBoundFieldType(pFieldName);
  }

  public override object GetBoundFieldValue(string pFieldName)
  {
    if(pFieldName == "UserName")
    {
      return _userNameValue;
    }

    return base.GetBoundFieldValue(pFieldName);
  }

  public override void SetBoundFieldValue(string pFieldName, object pValue)
  {
    if(pFieldName == "UserName")
    {
      _userNameValue = (string)pValue;
    }
    base.SetBoundFieldValue(pFieldName, pValue);
  }
}

// Use our custom node with a NodeTextBox node control which will edit the node data.
NodeTextBox tb = new NodeTextBox();
tb.AttachTo(tree);
tb.DataFieldName = "UserName";
tb.Editable = true;
tb.EditStartMode = eEditStartMode.Click;
tb.IsInBoundMode = true;

VirtualBindableNode node = new VirtualBindableNode();
node.AttachTo(tree);
' Custom node class that holds the bound value inside.
Class VirtualBindableNode
    Inherits BindableNode
    Private _userNameValue As String = "John Smith"
    ' data initial value.
    Protected Overrides Function GetBoundFieldType(pFieldName As String) As Type
        If pFieldName = "UserName" Then
            Return GetType(String)
        End If
        Return MyBase.GetBoundFieldType(pFieldName)
    End Function

    Public Overrides Function GetBoundFieldValue(pFieldName As String) As Object
        If pFieldName = "UserName" Then
            Return _userNameValue
        End If
        Return MyBase.GetBoundFieldValue(pFieldName)
    End Function

    Public Overrides Sub SetBoundFieldValue(pFieldName As String, pValue As Object)
        If pFieldName = "UserName" Then
            _userNameValue = DirectCast(pValue, String)
        End If
        MyBase.SetBoundFieldValue(pFieldName, pValue)
    End Sub
End Class

' Use our custom node with a NodeTextBox node control which will edit the node data.
Dim tb As New NodeTextBox()
tb.AttachTo(tree)
tb.DataFieldName = "UserName"
tb.Editable = True
tb.EditStartMode = eEditStartMode.Click
tb.IsInBoundMode = True

Dim node As New VirtualBindableNode()
node.AttachTo(tree)

As shown above, the GetBoundFieldType method is used to define the data type of the virtually bound property, the GetBoundFieldValue and the SetBoundFieldValue methods are used to retrieve and save the bound data, respectively.

Note that the IsInBoundMode node control property should be enabled which forces node control to manage bound data via GetBoundFieldValue and SetBoundFieldValue bindable node's methods.

 

 


Copyright © 2006-2016 ARMSoft

www.FlexibleTreeView.com