Skip to main content

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.v23.2.dll

NuGet Packages: DevExpress.Win.Navigation, DevExpress.Win.TreeList

Declaration

[DXCategory("Behavior")]
public event CustomColumnDataEventHandler CustomUnboundColumnData

Event Data

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

Remarks

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.UnboundDataType property 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.

Your CustomUnboundColumnData event handler must not dispose of the control’s data source, modify column settings, the control’s layout and object model.

Note

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

Note

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.

Example 1

This example demonstrates how to create an editable unbound column. The example uses a simple cache implementation within the CustomUnboundColumnData event handler to fetch custom data faster.

using DevExpress.XtraTreeList.Columns;

private void CreateUnboundColumn() {
    TreeListColumn column = treeList1.Columns.AddVisible("UnboundColumn");
    column.UnboundDataType = typeof(string);
}

Dictionary<int, string> storage = new Dictionary<int, string>();
private void treeList1_CustomUnboundColumnData(object sender, DevExpress.XtraTreeList.TreeListCustomColumnDataEventArgs e) {
    if(e.Column.FieldName == "UnboundColumn") {
        if(e.IsGetData)
            if(storage.ContainsKey(e.NodeID))
                e.Value = storage[e.NodeID];
            else
                e.Value = storage[e.NodeID] = string.Format("Unbound value {0}", e.NodeID);
        if(e.IsSetData)
            storage[e.NodeID] = e.Value.ToString();
    }
}

Example 2

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.

TreeList-CustomUnboundColumnDataEvent

View Example

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() {
            InitializeComponent();
            InitTreeList();
        }

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

            // Create and customize an unbound column.
            TreeListColumn unbColumnMarchChange = new TreeListColumn();
            unbColumnMarchChange.UnboundDataType = typeof(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";
            tlBandThisYear.Columns.Add(unbColumnMarchChange);
            // 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.
            treeList1.ForceInitialize();
            treeList1.BestFitColumns();
        }

        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;
        }
    }

}

The following code snippet (auto-collected from DevExpress Examples) contains a reference to the CustomUnboundColumnData event.

Note

The algorithm used to collect these code examples remains a work in progress. Accordingly, the links and snippets below may produce inaccurate results. If you encounter an issue with code examples below, please use the feedback form on this page to report the issue.

See Also