Unbound Rows

  • 7 minutes to read

The VGridControl control supports bound and unbound rows. This topic introduces unbound rows - rows that are not bound to any field in a grid's data source.


Bound and Unbound Rows

Bound rows obtain their data from a grid's data source, which is specified by the VGridControl.DataSource and VGridControl.DataMember properties. Their RowProperties.FieldName properties refer to valid fields in a data source.

An unbound row is not bound to any field in an underlying data source. You can provide data for unbound rows using one of two methods:

  • by specifying a formula (string expression) via the RowProperties.UnboundExpression property used to automatically evaluate values for this row. Expressions allow you to calculate values based on values of other rows. You can use constants, various functions and operators in expressions. See Expressions to learn about the syntax.
  • by handling the VGridControl.CustomUnboundData event. In this event, you can implement custom logic of any complexity.

    With this event, you can enable an end-user to edit values in unbound rows. When an end-user modifies a cell, the CustomUnboundData event fires allowing you to save the changes.


    The CustomUnboundData event fires only for visible unbound rows.

An unbound row must meet the following two requirements:

  • its field name (RowProperties.FieldName) must be set to a unique value and not refer to any field in a grid's data source;
  • the row's RowProperties.UnboundType property must be set to an appropriate value, according to the type of data the row is supposed to display (Boolean, DateTime, Decimal, Integer, String or Object). It should not be set to UnboundColumnType.Bound.

An unbound row's RowProperties.UnboundType property determines how it functions. First, it determines which default editor will be used to represent row values. For example, if the UnboundType property is set to UnboundColumnType.DateTime, the row will use a DateEdit in-place editor. Second, it determines how cell values will be aligned, and which validity rules should be applied to the row, etc.

Note that you can also assign a specific editor to a row via the RowProperties.RowEdit property and to a specific cell via the VGridControlBase.CustomRecordCellEdit and VGridControlBase.CustomRecordCellEditForEditing events.

If the UnboundType property is set to UnboundColumnType.Bound, it is assumed that the row is bound to a specific field in a grid's data source. This field is determined by the RowProperties.FieldName property.

Unbound Rows' Data

You can provide data for unbound rows either by creating an expression via the RowProperties.UnboundExpression property or by handling the VGridControl.CustomUnboundData event. To learn about the syntax of expressions, see Expressions.

At runtime, an end-user can edit an unbound row's expression via an Expression Editor. It can be opened via a context menu (if the RowProperties.ShowUnboundExpressionMenu option is enabled) or in code via the VGridControl.ShowUnboundExpressionEditor method.

By default, data editing is enabled in unbound row cells. However, you may wish to prevent an end-user from editing unbound rows. To make a row read-only, use the RowProperties.ReadOnly property.

If you want to save the changes made by end-users in unbound rows, you should populate an unbound row via the VGridControl.CustomUnboundData event. This event's IsGetData and IsSetData parameters determine the event's current mode of operation. If the IsGetData parameter is set to true (and consequently the IsSetData parameter is set to false), the event handler should supply data for an unbound row. A value should be assigned to the Value parameter according to the record currently being processed. The current record can be identified using the ListSourceRowIndex parameter, which specifies the record's index in a grid's data source.

If the IsSetData parameter is set to true (and consequently the IsGetData parameter is set to false), the event has been fired as a result of data modifications within a grid. In this case, the Value parameter contains modified data and should be stored for further use.


If you need to get or set specific cell values while handling the CustomUnboundData event, use methods provided by the bound data source. The event's ListSourceRowIndex parameter allows you to identify the current data record.

Do not use methods provided by the grid control (for example, VGridControlBase.GetCellValue and VGridControlBase.SetCellValue) to get/set cell values in a CustomUnboundData event.

Working with Unbound Rows

There is no difference between working with bound and unbound rows.

However, please keep in mind those situations in which unbound rows retrieve their data from a custom data source, and a record is added to or deleted from a grid's main data source. When a record is added, you usually need to add a new entry to the custom data source that corresponds to the new record in the grid. Similarly, when a record is deleted you usually need to delete the corresponding entry in the custom data source. To receive notifications about a record that has been added or removed, use the methods provided by the data source.

When printing or exporting a grid, the contents of unbound rows will be printed/exported as well.

Custom Display Text

With their editing feature disabled, unbound rows can be used to display custom read-only information. It is also possible to provide custom display text for cells using the VGridControlBase.CustomDrawRowValueCell event. The custom display text supplied via this event is not printed or exported.

Example - Implement Unbound Rows Via Event

Assume that a VGridControl control is bound to the [Order Details] table in the NWind database. The grid contains "Quantity", "UnitPrice" and "Discount" rows which are bound to the corresponding fields in the database table. The example below shows how to add an unbound row to the grid, to display the amount of each order according to the expression: QuantityUnitPrice(1-Discount).

The result is displayed below:


using DevExpress.XtraVerticalGrid;
using DevExpress.XtraVerticalGrid.Rows;
using DevExpress.Data;
using DevExpress.Utils;
using DevExpress.XtraVerticalGrid.Events;

// Unbound row.
EditorRow rowTotal = null;

private void Form1_Load(object sender, EventArgs e) {
    // ...
    vGridControl1.CustomUnboundData += new CustomDataEventHandler(vGridControl1_CustomUnboundData);
    // Create and initialize the unbound Total row.
    rowTotal = new EditorRow();
    rowTotal.Properties.Caption = "Total";
    rowTotal.Properties.FieldName = "Total";
    // Specify format settings.
    rowTotal.Properties.Format.FormatType = FormatType.Numeric;
    rowTotal.Properties.Format.FormatString = "c";            
    rowTotal.Properties.ImageIndex = 1;
    // Disable editing.
    rowTotal.Properties.ReadOnly = true;            
    rowTotal.Properties.UnboundType = UnboundColumnType.Decimal;
    // Customize the appearance settings.
    rowTotal.Appearance.BackColor = Color.LightYellow;
    rowTotal.Appearance.Font = new System.Drawing.Font(rowTotal.Appearance.Font, 

// Provide data for the Total row.
private void vGridControl1_CustomUnboundData(object sender, CustomDataEventArgs e) {
    VGridControl vGrid = sender as VGridControl;
    if (e.Row == rowTotal && e.IsGetData) {
        DataRowView row = (DataRowView)vGrid.GetRecordObject(e.ListSourceRowIndex);
        decimal unitPrice = Convert.ToDecimal(row["UnitPrice"]);
        decimal quantity = Convert.ToDecimal(row["Quantity"]);
        decimal discount = Convert.ToDecimal(row["Discount"]); ;
        e.Value = unitPrice * quantity * (1 - discount);