A newer version of this page is available. Switch to the current version.

TreeList.CustomUnboundColumnData Event

Allows you to provide data to unbound columns, and save their modified records to an external source.

Namespace: DevExpress.XtraTreeList

Assembly: DevExpress.XtraTreeList.v19.1.dll


public event CustomColumnDataEventHandler CustomUnboundColumnData
Public Event CustomUnboundColumnData As CustomColumnDataEventHandler

Event Data

The CustomUnboundColumnData event's data class is DevExpress.XtraTreeList.TreeListCustomColumnDataEventArgs.


Unbound columns are not bound to any field in the underlying data source. Data for these columns can be provided either by creating an expression using the TreeListColumn.UnboundExpression property or by handling the CustomUnboundColumnData event. To learn about the syntax of expressions, see Expressions.

You can create an unbound (calculated) column as follows:

  1. Create a TreeListColumn object and add it to the TreeList.Columns collection.
  2. Set the column's TreeListColumn.UnboundType property to any of the following values: Boolean, DateTime, Decimal, Integer, Object or String (according to the type of data the column is supposed to display).
  3. Set the column's TreeListColumn.FieldName to a unique value.

The CustomUnboundColumnData event fires only for visible unbound columns. It fires in two cases:

  • When the treelist is loaded, it raises the CustomUnboundColumnData event to populate the unbound columns. The event's IsGetData parameter will be set to true (consequently the IsSetData parameter will be set to false). In this case, you need to supply data for the currently processed cell. Obtain the required value from a custom data source, and assign it to the Value parameter.
  • When an unbound column's data is modified from the treelist, the CustomUnboundColumnData event is fired with the IsSetData parameter set to true (consequently the IsGetData parameter is set to false). In this case, you should save the modified data specified by the Value property back to the data source.

The CustomUnboundColumnData event is not raised if the TreeList.DataSource property equals null.


The CustomUnboundColumnData event fires for each cell. However, due to the treelist control's data processing algorithms, this event may fire repeatedly, multiple times, for each cell. The treelist control doesn't cache data you provided via the CustomUnboundColumnData event. If providing data via the event takes considerable time, you need to manually cache data.


This example creates a "Change from Previous Year" read-only unbound column in the TreeList control and populates this column with data using the TreeList.CustomUnboundColumnData event.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.Skins;
using DevExpress.LookAndFeel;
using DevExpress.UserSkins;
using DevExpress.XtraTreeList.Columns;

namespace TreeList_UnboundDataViaEvent {
    public partial class Form1 : XtraForm {
        public Form1() {

        void InitTreeList() {
            treeList1.DataSource = SalesDataGenerator.CreateData();

            // Create and customize an unbound column.
            TreeListColumn unbColumnMarchChange = new TreeListColumn();
            unbColumnMarchChange.UnboundType = DevExpress.XtraTreeList.Data.UnboundColumnType.Decimal;
            unbColumnMarchChange.Visible = true;
            unbColumnMarchChange.OptionsColumn.AllowEdit = false;
            unbColumnMarchChange.FieldName = "ChangeFromPrevYear";
            unbColumnMarchChange.Caption = "Change from Previous Year";
            unbColumnMarchChange.Format.FormatType = DevExpress.Utils.FormatType.Numeric;
            unbColumnMarchChange.Format.FormatString = "p2";
            // Change the appearance settings after the column is added to the TreeList.
            unbColumnMarchChange.AppearanceHeader.Font = new Font(unbColumnMarchChange.AppearanceHeader.Font, FontStyle.Bold);
            unbColumnMarchChange.AppearanceCell.BackColor = Color.LightYellow;
            // Subcribe to the event that provides data for unbound columns.
            treeList1.CustomUnboundColumnData += TreeList1_CustomUnboundColumnData;
            // Resize columns proportionally.

        private void TreeList1_CustomUnboundColumnData(object sender, DevExpress.XtraTreeList.TreeListCustomColumnDataEventArgs e) {
            if(e.IsGetData && e.Column.FieldName == "ChangeFromPrevYear") {
                SalesData currentRow = e.Row as SalesData;
                if (currentRow == null) return;
                e.Value = (currentRow.MarchSales - currentRow.MarchSalesPrev) / currentRow.MarchSalesPrev;

    public class SalesData {
        public SalesData(int id, int regionId, string region, decimal marchSales, decimal marchSalesPrev) {
            ID = id;
            RegionID = regionId;
            Region = region;
            MarchSales = marchSales;
            MarchSalesPrev = marchSalesPrev;
        public int ID { get; set; }
        public int RegionID { get; set; }
        public string Region { get; set; }
        public decimal MarchSales { get; set; }
        public decimal MarchSalesPrev { get; set; }

    public class SalesDataGenerator {
        public static List<SalesData> CreateData() {
            List<SalesData> sales = new List<SalesData>();
            sales.Add(new SalesData(0, -1, "Western Europe", 30540, 33000));
            sales.Add(new SalesData(1, 0, "Austria", 22000, 20000));
            sales.Add(new SalesData(2, 0, "Belgium", 13000, 9640));
            sales.Add(new SalesData(3, 0, "Denmark", 21000, 18100));
            sales.Add(new SalesData(4, 0, "Finland", 17000, 17420));
            sales.Add(new SalesData(5, 0, "France", 23020, 27000));
            sales.Add(new SalesData(6, 0, "Germany", 30540, 33000));
            sales.Add(new SalesData(7, 0, "Greece", 15600, 13200));
            sales.Add(new SalesData(8, 0, "Ireland", 9530, 10939));
            sales.Add(new SalesData(9, 0, "Italy", 17299, 19321));
            sales.Add(new SalesData(11, 0, "Netherlands", 8902, 9214));
            sales.Add(new SalesData(12, 0, "Norway", 5400, 7310));
            sales.Add(new SalesData(13, 0, "Portugal", 9220, 4271));
            sales.Add(new SalesData(14, 0, "Spain", 12900, 10300));
            sales.Add(new SalesData(15, 0, "Switzerland", 9323, 10730));
            sales.Add(new SalesData(16, 0, "United Kingdom", 14580, 13967));

            sales.Add(new SalesData(17, -1, "Eastern Europe", 22500, 24580));
            sales.Add(new SalesData(18, 17, "Belarus", 7315, 18800));
            sales.Add(new SalesData(19, 17, "Bulgaria", 6300, 2821));
            sales.Add(new SalesData(20, 17, "Croatia", 4200, 3890));
            sales.Add(new SalesData(21, 17, "Czech Republic", 19500, 15340));
            sales.Add(new SalesData(22, 17, "Hungary", 13495, 13900));
            sales.Add(new SalesData(23, 17, "Poland", 8930, 9440));
            sales.Add(new SalesData(24, 17, "Romania", 4900, 5100));
            sales.Add(new SalesData(25, 17, "Russia", 22500, 24580));

            sales.Add(new SalesData(26, -1, "North America", 31400, 32800));
            sales.Add(new SalesData(27, 26, "USA", 31400, 32800));
            sales.Add(new SalesData(28, 26, "Canada", 25390, 27000));

            sales.Add(new SalesData(29, -1, "South America", 16380, 15590));
            sales.Add(new SalesData(30, 29, "Argentina", 16380, 15590));
            sales.Add(new SalesData(31, 29, "Brazil", 4560, 5480));

            sales.Add(new SalesData(32, -1, "Asia", 20388, 22547));
            sales.Add(new SalesData(34, 32, "India", 4642, 5320));
            sales.Add(new SalesData(35, 32, "Japan", 9457, 12859));
            sales.Add(new SalesData(36, 32, "China", 20388, 22547));
            return sales;

See Also