Data Binding in WinUI TreeGrid

14 Apr 202117 minutes to read

SfTreeGrid is designed to display the self-relational and hierarchical data in tree structure with columns. The data binding can be achieved by assigning the data source to SfTreeGrid.ItemsSource property directly through self-relational binding or nested collection or retrieving the parent and child nodes items dynamically using RequestTreeItems event or LoadOnDemandCommand command.
If the data source implements INotifyCollectionChanged interface, then SfTreeGrid control will automatically refresh the UI when item is added, removed or while list cleared. When you add, remove item in ObservableCollection, SfTreeGrid automatically refresh the UI as ObservableCollection implements INotifyCollectionChanged. But when you do the same in List, SfTreeGrid will not refresh the UI automatically.

Below are the ways to bind the data source to SfTreeGrid.

Binding with IEnumerable

SfTreeGrid control supports to bind any collection that implements the IEnumerable interface. Data operations such as sorting is supported when you are binding collection derived from IEnumerable.

Binding with dynamic data object

SfTreeGrid control supports to bind dynamic data object. Below are the limitations when you are binding dynamic data object,

  1. In UWP, UI won’t get refreshed when you are changing the property value. This is limitation in UWP platform.
  2. SfTreeGrid doesn’t support LiveNodeUpdateMode - AllowDataShaping.

Binding Complex properties

SfTreeGrid control provides support to bind complex property to its columns. To bind the complex property to TreeGridColumn, set the complex property path to MappingName.

xmlns:treeGrid="using:Syncfusion.UI.Xaml.TreeGrid"

<treeGrid:SfTreeGrid x:Name="sfTreeGrid"
                       ChildPropertyName="Children"
                       ItemsSource="{Binding PersonDetails}"
                       ShowRowHeader="True">
            <treeGrid:SfTreeGrid.Columns>
                <treeGrid:TreeGridColumns>
                    <treeGrid:TreeGridTextColumn MappingName="FirstName" />
                    <treeGrid:TreeGridTextColumn MappingName="Address.City" />
                    <treeGrid:TreeGridTextColumn MappingName="Address.Country" />
                </treeGrid:TreeGridColumns>
            </treeGrid:SfTreeGrid.Columns>
 </treeGrid:SfTreeGrid>

Limitations when binding complex property:

SfTreeGrid doesn’t support LiveNodeUpdateMode - AllowDataShaping.

Binding Indexer properties

SfTreeGrid control provides support to bind an indexer property to its columns. To bind an indexer property to TreeGridColumn, set the indexer property path to MappingName.

<treeGrid:SfTreeGrid x:Name="sfTreeGrid"
                       AutoGenerateColumns="False"
                       ItemsSource="{Binding Employees}">
            <treeGrid:SfTreeGrid.Columns>
                <treeGrid:TreeGridTextColumn MappingName="FirstName" />
                <treeGrid:TreeGridTextColumn MappingName="LastName" />
                <treeGrid:TreeGridTextColumn MappingName="ShippersInfo[0].ShipperID" />
            </treeGrid:SfTreeGrid.Columns>
</treeGrid:SfTreeGrid>
this.sfTreeGrid.Columns.Add(new TreeGridTextColumn() {MappingName="ShippersInfo[0].ShipperID"});

Limitations when binding Indexer property:

SfTreeGrid doesn’t support LiveNodeUpdateMode - AllowDataShaping.

AutoExpandMode

By setting SfTreeGrid.AutoExpandMode property, you can let the SfTreeGrid to expand the nodes while loading.

Mode

Description

AllNodesExpanded All the nodes will be expanded while at the time of loading.
None None defines the node is not expanded when loading. By default, root nodes only will be displayed.
RootNodeExpanded Root nodes only will be expanded at the time of loading.
<treeGrid:SfTreeGrid Name="sfTreeGrid"
                       AutoExpandMode="AllNodesExpanded"
                       AutoGenerateColumns="False"
                       ChildPropertyName="ReportsTo"
                       ItemsSource="{Binding Employees}"
                       ParentPropertyName="ID" />
this.sfTreeGrid.AutoExpandMode = AutoExpandMode.AllNodesExpanded;

Expanding a tree node

You can expand a node based on its level or row index. Here is a list of ways to expand a node,

Method

Description

ExpandAllNodes()

Expands all the nodes including its inner leaf nodes

ExpandAllNodes(int level)

Expand all the nodes up to the specified level

ExpandAllNodes(TreeNode treeNode)

Expand the specific node and its child nodes

ExpandNode(int rowIndex)

Expand a node at the specific row Index

ExpandNode(TreeNode treeNode)

Expands the specific node.

Expand all the nodes

You can expand all the nodes programmatically at runtime by using SfTreeGrid.ExpandAllNodes method.

this.sfTreeGrid.ExpandAllNodes();

Expand the nodes based on its level

You can expand the nodes based on the level by using SfTreeGrid.ExpandAllNodes method by passing level as argument.

this.sfTreeGrid.ExpandAllNodes(1);

Expand the specific node

You can expand the specific node by using SfTreeGrid.ExpandNode method.

var node = sfTreeGrid.View.Nodes[0];
this.sfTreeGrid.ExpandNode(node);

You can expand the node at specific index also by using SfTreeGrid.ExpandNode method.

this.sfTreeGrid.ExpandNode(2);

Expand the specific node based on business object

You can expand the node corresponding to specific data object by resolving node and calling SfTreeGrid.ExpandNode method.

var data = (this.DataContext as EmployeeViewModel).Employees[0];
var node = this.sfTreeGrid.View.Nodes.GetNode(data);
this.sfTreeGrid.ExpandNode(node);

Expand all the nodes

You can expand the specific node and all its child nodes by using SfTreeGrid.ExpandAllNodes methods.

var node = sfTreeGrid.View.Nodes[0];
this.sfTreeGrid.ExpandAllNodes(node);

Cancel the node Expanding using NodeExpanding event

You can cancel the node expanding through SfTreeGrid.NodeExpanding event.

this.sfTreeGrid.NodeExpanding += SfTreeGrid_NodeExpanding;

private void SfTreeGrid_NodeExpanding(object sender, NodeExpandingEventArgs e)
{
    e.Cancel = true;
}

You can cancel the specific node being expanded by using SfTreeGrid.NodeExpanding event and Node property,

this.sfTreeGrid.NodeExpanding += SfTreeGrid_NodeExpanding;

private void SfTreeGrid_NodeExpanding(object sender, NodeExpandingEventArgs e)
{    
    if ((e.Node.Item as Employee).EmpID == 2)
        e.Cancel = true;
}

NodeExpanded Event

You can get the notification once a node is expanded from TreeGrid.NodeExpanded event and here you can get the expanded node and its child nodes.

this.sfTreeGrid.NodeExpanded += SfTreeGrid_NodeExpanded;

private void SfTreeGrid_NodeExpanded(object sender, NodeExpandedEventArgs e)
{
    var node = e.Node;
    var childNodes = e.Node.ChildNodes;
}

Collapsing a tree node

You can collapse all the tree nodes or specific node and its child nodes. Here is a list of ways to collapse a node,

Method

Description

CollapseAllNodes()

Collapse all the nodes in SfTreeGrid

CollapseAllNodes(TreeNode treeNode)

Collapse the specific node and its child nodes

CollapseNode(int rowIndex)

Collapse the node at specific row index

CollapseNode(TreeNode treeNode)

Collapse the specific node in SfTreeGrid

Collapse all the nodes

You can collapse all the nodes programmatically at runtime by using SfTreeGrid.CollapseAllNodes methods

this.sfTreeGrid.CollapseAllNodes();

Collapse the specific node

You can collapse the specific node by using SfTreeGrid.CollapseNode method.

var node = this.sfTreeGrid.View.Nodes[0];
this.sfTreeGrid.CollapseNode(node);

You can collapse the node at specific index also by using SfTreeGrid.CollapseNode method.

this.sfTreeGrid.CollapseNode(2);

Collapse the specific node based on business object

You can collapse the node corresponding to specific data object by resolving node and calling SfTreeGrid.CollapseNode method.

var data = (this.DataContext as EmployeeViewModel).Employees[0];
var node = this.sfTreeGrid.View.Nodes.GetNode(data);
this.sfTreeGrid.CollapseNode(node);

Collapse all the nodes

You can collapse the specific node and all its child nodes by using SfTreeGrid.CollapseAllNodes methods.

var node = this.sfTreeGrid.View.Nodes[0];
this.sfTreeGrid.CollapseAllNodes(node);

Cancel the node collapsing using NodeCollapsing Event

You can cancel the node collapsing operation through TreeGrid.NodeCollapsing event.

this.sfTreeGrid.NodeCollapsing += SfTreeGrid_NodeCollapsing;

private void SfTreeGrid_NodeCollapsing(object sender, NodeCollapsingEventArgs e)
{
    e.Cancel = true;
}

You can cancel the specific node being collapsed by using TreeGrid.NodeCollapsing event.

this.sfTreeGrid.NodeCollapsing += SfTreeGrid_NodeCollapsing;

private void SfTreeGrid_NodeCollapsing(object sender, NodeCollapsingEventArgs e)
{
    if ((e.Node.Item as Employee).EmpID == 2)
       e.Cancel = true;
}

NodeCollapsed Event

You can get the notification once a node is collapsed from TreeGrid.NodeCollapsed event and here you can get the collapsed node.

this.sfTreeGrid.NodeCollapsed += SfTreeGrid_NodeCollapsed;

private void SfTreeGrid_NodeCollapsed(object sender, NodeCollapsedEventArgs e)
{
    var node = e.Node;
}

Expand/Collapse a node based on mapping property

SfTreeGrid supports to expand/collapse the nodes based on the value of a boolean mapping property in the underlying data object by using SfTreeGrid.ExpandStateMappingName property. TreeGrid expand/collapse the node when the specified property value in underlying data object gets changed.

<treeGrid:SfTreeGrid Name="sfTreeGrid"
                       ExpandStateMappingName="IsExpanded"
                       ChildPropertyName="Children"
                       ItemsSource="{Binding PersonDetails}"
                       ShowCheckBox="True" />
this.sfTreeGrid.ExpandStateMappingName = "IsExpanded";

LiveNodeUpdateMode

SfTreeGrid listens and responds to the manipulation such as add, delete and data update (property change) at runtime. SfTreeGrid refreshes the sorting based on SfTreeGrid.LiveNodeUpdateMode property. If you set LiveNodeUpdateMode as AllowDataShaping, sorting will be refreshed on data manipulation and property change.

<treeGrid:SfTreeGrid  Name="sfTreeGrid"
                        AllowEditing="True"
                        AutoExpandMode="RootNodesExpanded"
                        LiveNodeUpdateMode="AllowDataShaping"
                        AutoGenerateColumns="False"
                        ChildPropertyName="ReportsTo"
                        ItemsSource="{Binding Employees}"
                        ParentPropertyName="ID" />
this.sfTreeGrid.LiveNodeUpdateMode = LiveNodeUpdateMode.AllowDataShaping;

Events

ItemsSourceChanged

SfTreeGrid.ItemsSourceChanged event occurs when the data source is changed by using ItemsSource property.

This event receives two arguments namely sender that handles SfTreeGrid and TreeGridItemsSourceChangedEventArgs as objects.
The TreeGridItemsSourceChangedEventArgs object contains the following properties:

View

SfTreeGrid has the View property of type TreeGridView. View is responsible for maintaining and manipulating the nodes and other advanced operations like Sorting. When you bind Collection to ItemsSource property of SfTreeGrid or wire RequestTreeItems event, then View will be created and maintains the operations on nodes.

SfTreeGrid creates different types of views derived from TreeGridView based on data population methods.

TreeGridSelfRelationalView - While populating data using self-relational binding.

TreeGridNestedView - While populating data using nested collection.

TreeGridUnboundView - While populating data with RequestTreeItems event or LoadOnDemandCommand command.

Events

The following events are associated with View.

RecordPropertyChanged

This event is raised when the DataModel property value is changed, if the DataModel implements the INotifyPropertyChanged interface. The event receives with two arguments namely sender that handles the DataModel and PropertyChangedEventArgs as object.

PropertyChangedEventArgs has below property,

PropertyName – It denotes the PropertyName of the changed value.

NodeCollectionChanged

This event is raised whenever there is some change in nodes collection. The event receives two arguments namely sender that handles View object and NotifyCollectionChangedEventArgs as object.
NotifyCollectionChangedEventArgs has below properties,

  • Action - It contains the current action. (i.e.) Add, Remove, Move, Replace, Reset.
  • NewItems - It contains the list of new items involved in the change.
  • OldItems - It contains the list of old items affected by the Action.
  • NewStartingIndex - It contains the index at which the change occurred.
  • OldStartingIndex - It contains the index at which the Action occurred.

SourceCollectionChanged

This event is raised when you make changes in SourceCollection for example add or remove the collection. The event receives two arguments namely sender that handles that handles View object and NotifyCollectionChangedEventArgs as object.
NotifyCollectionChangedEventArgs has below properties,

  • Action - It contains the current action. (i.e) Add, Remove, Move, Replace, Reset.
  • NewItems - It contains the list of new items involved in the change.
  • OldItems - It contains the list of old items affected by the Action.
  • NewStartingIndex - It contains the index at which the change occurred.
  • OldStartingIndex- It contains the index at which the Action occurred.

Methods

The following are the methods that are associated with View which can be used to defer refresh the view.

DeferRefresh

Enter the defer cycle so that you can perform all data operations in view and update once. You can refresh the nodes or completely recreates the nodes by using TreeViewRefreshMode parameter.

using (this.sfTreeGrid.View.DeferRefresh(TreeViewRefreshMode.NodeRefresh))
{
    this.sfTreeGrid.SortColumnDescriptions.Add(new SortColumnDescription() { ColumnName = "FirstName", SortDirection = ListSortDirection.Descending });
    this.sfTreeGrid.SortColumnDescriptions.Add(new SortColumnDescription() { ColumnName = "ID", SortDirection = ListSortDirection.Descending });
}

BeginInit and EndInit

When BeginInit method is called, it suspends all the updates until EndInit method is called. You can perform all the update with in these methods and update the view at once. You can refresh the nodes or completely recreates the nodes by using TreeViewRefreshMode parameter.

this.sfTreeGrid.View.BeginInit(TreeViewRefreshMode.DeferRefresh);
this.sfTreeGrid.SortColumnDescriptions.Add(new SortColumnDescription() { ColumnName = "FirstName", SortDirection = ListSortDirection.Descending });
this.sfTreeGrid.SortColumnDescriptions.Add(new SortColumnDescription() { ColumnName = "ID", SortDirection = ListSortDirection.Descending });
this.sfTreeGrid.View.EndInit();

NOTE

View has properties (EnableRecursiveChecking, LiveNodeUpdateMode , RecursiveCheckingMode,..)that already defined in SfTreeGrid. It is recommended to set those properties via SfTreeGrid.