windowsforms-9424-controls-and-libraries-vertical-grid-binding-to-data-unbound-rows.md
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 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:
An unbound row must meet the following two requirements:
The UnboundDataType property determines the default cell editor, value alignment and validity rules.
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 UnboundDataType property is not set it is assumed that the row is bound to a data source field (RowProperties.FieldName).
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.
Note
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.
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.
To reload data in unbound rows and redraw the control on-screen, call the VGridControlBase.LayoutChanged method. The control also reloads data in unbound rows when you sort or filter data.
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.
This example demonstrates how to create an editable unbound row. It uses a simple cache implementation within the CustomUnboundData event handler to fetch custom data faster.
using DevExpress.XtraVerticalGrid.Rows;
private void CreateUnboundRow() {
EditorRow row = vGridControl1.Rows.AddEditorRow("UnboundRow");
row.Properties.UnboundDataType = typeof(string);
}
Dictionary<int, string> storage = new Dictionary<int, string>();
private void vGridControl1_CustomUnboundData(object sender, DevExpress.XtraVerticalGrid.Events.CustomDataEventArgs e) {
if(e.RowProperties.FieldName == "UnboundRow") {
if(e.IsGetData)
if(storage.ContainsKey(e.ListSourceRowIndex))
e.Value = storage[e.ListSourceRowIndex];
else
e.Value = storage[e.ListSourceRowIndex] = string.Format("Unbound value {0}", e.ListSourceRowIndex);
if(e.IsSetData)
storage[e.ListSourceRowIndex] = e.Value.ToString();
}
}
Imports DevExpress.XtraVerticalGrid.Rows
Private Sub CreateUnboundRow()
Dim row As EditorRow = vGridControl1.Rows.AddEditorRow("UnboundRow")
row.Properties.UnboundDataType = GetType(String)
End Sub
Private storage As New Dictionary(Of Integer, String)()
Private Sub vGridControl1_CustomUnboundData(ByVal sender As Object, ByVal e As DevExpress.XtraVerticalGrid.Events.CustomDataEventArgs)
If e.RowProperties.FieldName = "UnboundRow" Then
If e.IsGetData Then
If storage.ContainsKey(e.ListSourceRowIndex) Then
e.Value = storage(e.ListSourceRowIndex)
Else
storage(e.ListSourceRowIndex) = String.Format("Unbound value {0}", e.ListSourceRowIndex)
e.Value = storage(e.ListSourceRowIndex)
End If
End If
If e.IsSetData Then
storage(e.ListSourceRowIndex) = e.Value.ToString()
End If
End If
End Sub
In the following example, it is assumed that the Vertical Grid is bound to a table that contains the “Quantity”, “UnitPrice” and “Discount” fields. The code below adds an unbound row that calculates the total order amount according to the following expression: Quantity*UnitPrice*(1-Discount).
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";
// Disable edit operations.
rowTotal.Properties.ReadOnly = true;
vGridControl1.Rows.Add(rowTotal);
rowTotal.Properties.UnboundDataType = typeof(decimal);
// Customize the appearance settings.
rowTotal.Appearance.BackColor = Color.FromArgb(179, 226, 221);
rowTotal.Appearance.Font = new System.Drawing.Font(rowTotal.Appearance.Font,
System.Drawing.FontStyle.Bold);
}
// 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);
}
}
Imports DevExpress.XtraVerticalGrid
Imports DevExpress.XtraVerticalGrid.Rows
Imports DevExpress.Data
Imports DevExpress.Utils
Imports DevExpress.XtraVerticalGrid.Events
' Unbound row.
Dim rowTotal As EditorRow
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'...
AddHandler VGridControl1.CustomUnboundData, AddressOf 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"
' Disable edit operations.
rowTotal.Properties.ReadOnly = True
VGridControl1.Rows.Add(rowTotal)
rowTotal.Properties.UnboundDataType = GetType(Decimal)
' Customize the appearance settings.
rowTotal.Appearance.BackColor = Color.FromArgb(179, 226, 221)
rowTotal.Appearance.Font = New System.Drawing.Font(rowTotal.Appearance.Font, _
System.Drawing.FontStyle.Bold)
End Sub
' Provide data for the Total row.
Private Sub VGridControl1_CustomUnboundData(ByVal sender As System.Object, _
ByVal e As CustomDataEventArgs)
Dim vGrid As VGridControl = sender
If e.Row Is rowTotal And e.IsGetData Then
Dim row As DataRowView = vGrid.GetRecordObject(e.ListSourceRowIndex)
Dim unitPrice As Decimal = Convert.ToDecimal(row("UnitPrice"))
Dim quantity As Decimal = Convert.ToDecimal(row("Quantity"))
Dim discount As Decimal = Convert.ToDecimal(row("Discount"))
e.Value = unitPrice * quantity * (1 - discount)
End If
End Sub