Back to Devexpress

Iterate Through Rows and Cells in Code

wpf-6122-controls-and-libraries-data-grid-grid-view-data-layout-iterate-through-rows.md

latest15.3 KB
Original Source

Iterate Through Rows and Cells in Code

  • Oct 29, 2021
  • 7 minutes to read

This topic demonstrates how to access data items one by one. Refer to the Processing Group Rows topic for information on how to process group rows.

Iterate Through Rows

The GridControl identifies data rows by their handles or visible indexes. The DataControlBase.VisibleRowCount property returns the total number of visible group and data rows. To iterate through rows, use a counter from 0 to the value of the DataControlBase.VisibleRowCount property. In this code sample, we use the GridControl.GetRowHandleByVisibleIndex method to obtain row handles:

xaml
<dxg:GridControl x:Name="grid" ItemsSource="{Binding Source}" .../>
csharp
List<int> rowHandles = new List<int>();
for (int i = 0; i < grid.VisibleRowCount; i++) {
    int rowHandle = grid.GetRowHandleByVisibleIndex(i);
    rowHandles.Add(rowHandle);
}
vb
Dim rowHandles As List(Of Integer) = New List(Of Integer)()

For i As Integer = 0 To grid.VisibleRowCount - 1
    Dim rowHandle As Integer = grid.GetRowHandleByVisibleIndex(i)
    rowHandles.Add(rowHandle)
Next

The DataControlBase.VisibleRowCount property does not consider:

Note

When you display the New Item Row at the bottom of the GridControl, the DataControlBase.VisibleRowCount property considers it as a regular row.

To iterate through collapsed rows in a group, use the GridControl.GetChildRowCount method. This method returns the current count of rows in the group. Create a counter similar to the previous one, and use the GridControl.GetChildRowHandle method to obtain handles of rows in the group. Use the GridControl.IsGroupRowHandle method to check that the row is a group row.

The following example shows how to obtain the handles of all data rows (including rows in collapsed groups) in the View, except rows that are filtered out:

csharp
private List<int> GetDataRowHandles() {
    List<int> rowHandles = new List<int>();
    for (int i = 0; i < grid.VisibleRowCount; i++) {
        int rowHandle = grid.GetRowHandleByVisibleIndex(i);
        if (grid.IsGroupRowHandle(rowHandle)) {
            if (!grid.IsGroupRowExpanded(rowHandle)) {
                rowHandles.AddRange(GetDataRowHandlesInGroup(rowHandle));
            }
        }
        else
            rowHandles.Add(rowHandle);
    }
    return rowHandles;
}
private List<int> GetDataRowHandlesInGroup(int groupRowHandle) {
    List<int> rowHandles = new List<int>();
    for (int i = 0; i < grid.GetChildRowCount(groupRowHandle); i++) {
        int rowHandle = grid.GetChildRowHandle(groupRowHandle, i);
        if (grid.IsGroupRowHandle(rowHandle)) {
            rowHandles.AddRange(GetDataRowHandlesInGroup(rowHandle));
        }
        else
            rowHandles.Add(rowHandle);
    }
    return rowHandles;
}
vb
Private Function GetDataRowHandles() As List(Of Integer)
    Dim rowHandles As List(Of Integer) = New List(Of Integer)()

    For i As Integer = 0 To grid.VisibleRowCount - 1
        Dim rowHandle As Integer = grid.GetRowHandleByVisibleIndex(i)

        If grid.IsGroupRowHandle(rowHandle) Then

            If Not grid.IsGroupRowExpanded(rowHandle) Then
                rowHandles.AddRange(GetDataRowHandlesInGroup(rowHandle))
            End If
        Else
            rowHandles.Add(rowHandle)
        End If
    Next

    Return rowHandles
End Function

Private Function GetDataRowHandlesInGroup(ByVal groupRowHandle As Integer) As List(Of Integer)
    Dim rowHandles As List(Of Integer) = New List(Of Integer)()

    For i As Integer = 0 To grid.GetChildRowCount(groupRowHandle) - 1
        Dim rowHandle As Integer = grid.GetChildRowHandle(groupRowHandle, i)

        If grid.IsGroupRowHandle(rowHandle) Then
            rowHandles.AddRange(GetDataRowHandlesInGroup(rowHandle))
        Else
            rowHandles.Add(rowHandle)
        End If
    Next

    Return rowHandles
End Function

Iterate Through Cells

The GridControl defines cells by a row handle and a column object. To iterate through cells, extend the technique described in the Iterate Through Rows section and iterate through the GridControl.Columns or GridViewBase.VisibleColumns / TreeListView.VisibleColumns collection to access visible cells:

csharp
for (int i = 0; i < grid.VisibleRowCount; i++) {
    int rowHandle = grid.GetRowHandleByVisibleIndex(i);
    foreach (var column in grid.Columns) {
        var cellValue = grid.GetCellValue(rowHandle, column);
    }
}
vb
For i As Integer = 0 To grid.VisibleRowCount - 1
    Dim rowHandle As Integer = grid.GetRowHandleByVisibleIndex(i)

    For Each column In grid.Columns
        Dim cellValue = grid.GetCellValue(rowHandle, column)
    Next
Next

To iterate through columns in all bands, use the GridControl.Columns or GridViewBase.VisibleColumns collection. To iterate through columns in the band, obtain it from the GridControl.Bands collection and use the GridControlBand.Columns collection property.

Iterate Through Nodes

The TreeListView represents nodes as rows. You can use the techniques listed above to iterate through visible nodes and their cells. Refer to the Iterate Through Nodes topic for more information.

Iterate Through Detail Rows in the Master-Detail GridControl

The GridControl includes the following types of detail descriptors:

Note

The detail GridControl is available only if the master row is expanded.

DataControlDetailDescriptor

To iterate through the detail rows, you need to access detail GridControl‘s instances. Use the technique described in the Iterate Through Rows section and use the GridControl.IsMasterRowExpanded method to check that a master row is expanded. Use the GridControl.GetDetail method to obtain the expanded detail GridControl and iterate through its rows:

csharp
Dictionary<int, List<int>> master_detail = new Dictionary<int, List<int>>();

for (int i = 0; i < masterGridControl.VisibleRowCount; i++) {
    int rowHandle = masterGridControl.GetRowHandleByVisibleIndex(i);
    List<int> details = new List<int>();
    master_detail[rowHandle] = details;
    if (masterGridControl.IsMasterRowExpanded(rowHandle)) {
        var detailGrid = masterGridControl.GetDetail(rowHandle) as GridControl;
        for (int j = 0; j < detailGrid.VisibleRowCount; j++) {
            int detailRowHandle = detailGrid.GetRowHandleByVisibleIndex(j);
            details.Add(detailRowHandle);
        }
    }
}
vb
Dim master_detail As Dictionary(Of Integer, List(Of Integer)) = New Dictionary(Of Integer, List(Of Integer))()

For i As Integer = 0 To masterGridControl.VisibleRowCount - 1
    Dim rowHandle As Integer = masterGridControl.GetRowHandleByVisibleIndex(i)
    Dim details As List(Of Integer) = New List(Of Integer)()
    master_detail(rowHandle) = details

    If masterGridControl.IsMasterRowExpanded(rowHandle) Then
        Dim detailGrid = TryCast(masterGridControl.GetDetail(rowHandle), GridControl)

        For j As Integer = 0 To detailGrid.VisibleRowCount - 1
            Dim detailRowHandle As Integer = detailGrid.GetRowHandleByVisibleIndex(j)
            details.Add(detailRowHandle)
        Next
    End If
Next

Use the DataViewBase.FocusedView property to access the focused detail GridControl and iterate through its rows:

csharp
var focusedDetail = masterView.FocusedView as TableView;
if (focusedDetail != null) {
    List<int> rowHandles = new List<int>();
    for (int i = 0; i < focusedDetail.Grid.VisibleRowCount; i++) {
        int rowHandle = focusedDetail.Grid.GetRowHandleByVisibleIndex(i);
        rowHandles.Add(rowHandle);
    }
}
vb
Dim focusedDetail = TryCast(masterView.FocusedView, TableView)

If focusedDetail IsNot Nothing Then
    Dim rowHandles As List(Of Integer) = New List(Of Integer)()

    For i As Integer = 0 To focusedDetail.Grid.VisibleRowCount - 1
        Dim rowHandle As Integer = focusedDetail.Grid.GetRowHandleByVisibleIndex(i)
        rowHandles.Add(rowHandle)
    Next
End If

ContentDetailDescriptor

In the ContentDetailDescriptor, you can only obtain content visible in the GridControl‘s View.

To iterate through the detail rows, you need to access detail GridControl‘s instances. Use the LayoutTreeHelper class to iterate through the master GridControl‘s visual tree and access the detail GridControl‘s rows:

csharp
var detailGrids = LayoutTreeHelper.GetVisualChildren(masterGridControl).OfType<GridControl>();

foreach(var detailGrid in detailGrids) {
    List<int> rowHandles = new List<int>();
    for (int i = 0; i < detailGrid.VisibleRowCount; i++) {
        int rowHandle = detailGrid.GetRowHandleByVisibleIndex(i);
        rowHandles.Add(rowHandle);
    }
}
vb
Dim detailGrids = LayoutTreeHelper.GetVisualChildren(masterGridControl).OfType(Of GridControl)()

For Each detailGrid In detailGrids
    Dim rowHandles As List(Of Integer) = New List(Of Integer)()

    For i As Integer = 0 To detailGrid.VisibleRowCount - 1
        Dim rowHandle As Integer = detailGrid.GetRowHandleByVisibleIndex(i)
        rowHandles.Add(rowHandle)
    Next
Next

TabViewDetailDescriptor

The TabViewDetailDescriptor displays different types of details (ContentDetailDescriptor and DataControlDetailDescriptor) in its tabs. The GridControl creates a visual element only for the selected tab. To iterate through detail rows in the tab, use a technique described in the detail descriptor topic.

The GridControl.GetDetail method’s override accepts the DataControlDetailDescriptor objects. Use this override to obtain the GridControl shown in the TabViewDetailDescriptor’s tabs:

xaml
<dxg:GridControl.DetailDescriptor>
    <dxg:TabViewDetailDescriptor>
        <dxg:DataControlDetailDescriptor x:Name="firstDetailDescriptor" ItemsSourceBinding="{Binding Data}">
            <dxg:GridControl AutoGenerateColumns="AddNew" x:Name="detailGridControl">
                <dxg:GridControl.View>
                    <dxg:TableView x:Name="detailView"/>
                </dxg:GridControl.View>
            </dxg:GridControl>
        </dxg:DataControlDetailDescriptor>
    </dxg:TabViewDetailDescriptor>
</dxg:GridControl.DetailDescriptor>
csharp
Dictionary<int, List<int>> master_detail = new Dictionary<int, List<int>>();

for (int i = 0; i < masterGridControl.VisibleRowCount; i++) {

    int rowHandle = masterGridControl.GetRowHandleByVisibleIndex(i);

    List<int> details = new List<int>();
    master_detail[rowHandle] = details;

    if (masterGridControl.IsMasterRowExpanded(rowHandle)) {

        var detailGrid = masterGridControl.GetDetail(rowHandle, firstDetailDescriptor) as GridControl;
        if (detailGrid == null)
            return;

        for (int j = 0; j < detailGrid.VisibleRowCount; j++) {
            int detailRowHandle = detailGrid.GetRowHandleByVisibleIndex(j);
            details.Add(detailRowHandle);
        }
    }
}
vb
Dim master_detail As Dictionary(Of Integer, List(Of Integer)) = New Dictionary(Of Integer, List(Of Integer))()

For i As Integer = 0 To masterGridControl.VisibleRowCount - 1
    Dim rowHandle As Integer = masterGridControl.GetRowHandleByVisibleIndex(i)
    Dim details As List(Of Integer) = New List(Of Integer)()
    master_detail(rowHandle) = details

    If masterGridControl.IsMasterRowExpanded(rowHandle) Then
        Dim detailGrid = TryCast(masterGridControl.GetDetail(rowHandle, firstDetailDescriptor), GridControl)
        If detailGrid Is Nothing Then Return

        For j As Integer = 0 To detailGrid.VisibleRowCount - 1
            Dim detailRowHandle As Integer = detailGrid.GetRowHandleByVisibleIndex(j)
            details.Add(detailRowHandle)
        Next
    End If
Next