public virtual List<List<string>> GetFormTable (bool selected) { var exportTable = new List<List<string>>(); IList<int> exportedRows, exportedColumns; if (selected && treeDataGridView.SelectedCells.Count > 0 && !treeDataGridView.AreAllCellsSelected(false)) { var selectedRows = new Set<int>(); var selectedColumns = new Map<int, int>(); // ordered by DisplayIndex foreach (DataGridViewCell cell in treeDataGridView.SelectedCells) { selectedRows.Add(cell.RowIndex); selectedColumns[cell.OwningColumn.DisplayIndex] = cell.ColumnIndex; } exportedRows = selectedRows.ToList(); exportedColumns = selectedColumns.Values; } else { exportedRows = treeDataGridView.Rows.Cast<DataGridViewRow>().Select(o => o.Index).ToList(); exportedColumns = treeDataGridView.GetVisibleColumnsInDisplayOrder().Select(o => o.Index).ToList(); } // add column headers exportTable.Add(new List<string>()); foreach (var columnIndex in exportedColumns) exportTable.Last().Add(treeDataGridView.Columns[columnIndex].HeaderText); foreach (int rowIndex in exportedRows) { /* TODO: how to handle non-root rows? var row = rows[rowIndex]; // skip non-root rows or filtered rows if (rowIndexHierarchy.Count > 1 || getRowFilterState(row) == RowFilterState.Out) continue;*/ var rowIndexHierarchy = treeDataGridView.GetRowHierarchyForRowIndex(rowIndex); var rowText = new List<string>(); foreach (var columnIndex in exportedColumns) { object value = treeDataGridView[columnIndex, rowIndex].Value ?? String.Empty; rowText.Add(value.ToString()); if (columnIndex == 0 && rowIndexHierarchy.Count > 1) { int indent = (rowIndexHierarchy.Count - 1) * 2; rowText[rowText.Count - 1] = new string(' ', indent) + rowText[rowText.Count - 1]; } } exportTable.Add(rowText); } return exportTable; }