Tutorial: Unbound Columns

  • 4 minutes to read

This walkthrough is a transcript of the Unbound Columns video available on the DevExpress YouTube Channel.

In this tutorial, you will learn how to add columns whose values are not stored in the data source and are calculated using a pre-defined expression or specified with an event handler. You'll also see how you can provide separate storage for values displayed in these unbound columns.

Data for the unbound columns will be calculated based on values of the Quantity, UnitPrice and Discount columns.

Creating Unbound Columns and Specifying Expressions for them at Design Time

Select a grid control and then click its smart tag. Click Add Column twice to create two new columns.

DataGridBinding_AddingNewColumns

Resize the columns to make them wider. Click the first created column and set its GridColumn.FieldName to a unique string: "DiscountAmount".

DataGridBinding_UnboundColumnFieldName

Then, set the column's GridColumn.UnboundType property to any value other than UnboundColumnType.Bound. The column will display decimal values in this case.

DataGridBinding_UnboundTypeProperty

Use the GridColumn.UnboundExpression property to specify an expression used to calculate column values. Click the ellipsis button to open the Expression Editor, which will allow you to create formulas using various functions, operators, data field values, and constants. Create a simple expression that multiplies three existing fields.

DataGridBinding_ExpressionForUnboundColumn

To make this unbound column read-only, set the OptionsColumn.AllowEdit property to false.

Now format the values of the two columns as currency. Hold down the CTRL or SHIFT key and click another column. This selects two columns simultaneously. In the Properties grid, expand GridColumn.DisplayFormat and set FormatInfo.FormatType to FormatType.Numeric and FormatInfo.FormatString to c2.

DataGridBinding_UnboundColumnsDisplayFormat

Run the application. The first column displays calculated data and formats it as currency.

DataGridBinding_UnbounColumnResult

Editing Expressions for Unbound Columns at Runtime

It is possible to allow an end-user to modify expressions for unbound columns at runtime. To accomplish this, set the column's GridColumn.ShowUnboundExpressionMenu property to true.

DataGridBinding_ShowUnboundExpressionMenu

The column's context menu now provides the Expression Editor... command. When it's invoked, the Expression Editor dialog opens allowing you to modify the expression.

DataGridBinding_ExpressionEditorMenuItem

Providing Data for Unbound Columns Using an Event

For the second column, whose data will be provided later using an event, we also need to specify a unique GridColumn.FieldName and set its GridColumn.UnboundType property to UnboundColumnType.Decimal.

Supply values for the second unbound column by handling a dedicated event. Select gridView1 and switch to the Events page in the Properties grid. Subscribe to the ColumnView.CustomUnboundColumnData event.

The ColumnView.CustomUnboundColumnData event fires each time a column value is about to be displayed onscreen, and also after a column cell is modified and data posting is required. Values for the Total column will be calculated from Quantity, UnitPrice and Discount column values. First, you need to retrieve these values using methods of the bound data source. The grid control provides a helper ColumnView.GetListSourceRowCellValue method to do this. Second, calculate a value for the unbound column and assign it to the CustomColumnDataEventArgs.Value event parameter.


private void gridView_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) {
    GridView view = sender as GridView;
    if(view == null) return;
    int rowIndex = e.ListSourceRowIndex;
    decimal unitPrice = Convert.ToDecimal(view.GetListSourceRowCellValue(rowIndex, "UnitPrice"));
    decimal quantity = Convert.ToDecimal(view.GetListSourceRowCellValue(rowIndex, "Quantity"));
    decimal discount = Convert.ToDecimal(view.GetListSourceRowCellValue(rowIndex, "Discount"));
    if (e.Column.FieldName != "Total") return;
    if (e.IsSetData)
        e.Value = unitPrice * quantity * (1 - discount);
}

Run the application. The Total column displays data provided by the event handler.

DataGridBinding_UnbounColumnResult2

This column is not read-only. Therefore, you can modify cells, but the changes will not be saved.

Implementing Data Posting for Unbound Columns

The data grid does not store or cache values of unbound columns. It's up to you to implement data posting. To illustrate the data posting feature, modify the code.

In this code, values for the Total column are stored in a dictionary. When an end-user modifies a cell, the ColumnView.CustomUnboundColumnData event fires and its CustomColumnDataEventArgs.IsSetData parameter equals to true. The new value is saved in the dictionary for later use.


Dictionary<int, decimal> customTotals = new Dictionary<int, decimal>();

private void gridView1_CustomUnboundColumnData(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDataEventArgs e) {
    GridView view = sender as GridView;
    if(view == null) return;
    int rowIndex = e.ListSourceRowIndex;
    decimal unitPrice = Convert.ToDecimal(view.GetListSourceRowCellValue(rowIndex, "UnitPrice"));
    decimal quantity = Convert.ToDecimal(view.GetListSourceRowCellValue(rowIndex, "Quantity"));
    decimal discount = Convert.ToDecimal(view.GetListSourceRowCellValue(rowIndex, "Discount"));
    if (e.Column.FieldName != "Total") return;
    if (e.IsGetData) {
        if (!customTotals.ContainsKey(rowIndex))
            customTotals.Add(rowIndex, unitPrice * quantity * (1 - discount));
        e.Value = customTotals[rowIndex];
    }
    if (e.IsSetData) {
        customTotals[rowIndex] = Convert.ToDecimal(e.Value);
    }
}

Run the application again. Try modifying values to confirm that the changes were saved.

See Also