2

Is there a way to get an iteratable collection of all the cells in a DataGrid regardless of whether they are selected or not

H.B.
  • 166,899
  • 29
  • 327
  • 400
DanBrum
  • 419
  • 1
  • 7
  • 18

3 Answers3

3

If you mean DataGridCells you could use Vincent Sibals helper functions to iterate over all rows DataGrid.Items and columns DataGrid.Columns.

public DataGridCell GetCell(int row, int column)
{
    DataGridRow rowContainer = GetRow(row);

    if (rowContainer != null)
    {
        DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);

        // try to get the cell but it may possibly be virtualized
        DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
        if (cell == null)
        {
            // now try to bring into view and retreive the cell
            DataGrid_Standard.ScrollIntoView(rowContainer, DataGrid_Standard.Columns[column]);
            cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(column);
        }
        return cell;
    }
    return null;
}

public DataGridRow GetRow(int index)
{
    DataGridRow row = (DataGridRow)DataGrid_Standard.ItemContainerGenerator.ContainerFromIndex(index);
    if (row == null)
    {
        // may be virtualized, bring into view and try again
        DataGrid_Standard.ScrollIntoView(DataGrid_Standard.Items[index]);
        row = (DataGridRow)DataGrid_Standard.ItemContainerGenerator.ContainerFromIndex(index);
    }
    return row;
}

Edit

If grid is your DataGrid you get a list of all DataGridCells like this:

List<DataGridCell> allCellList = new List<DataGridCell>();

for (int i = 0; i < grid.Items.Count; i++)
{
    for (int j = 0; j < grid.Columns.Count; j++)
    {
        allCellList.Add(grid.GetCell(i, j));
    }
}
LPL
  • 16,827
  • 6
  • 51
  • 95
  • 1
    GetRow works but in the GetCell method the compiler won't let me use GetVisualChild with type arguments, and will only accept an integer as the argument. – DanBrum Jul 25 '12 at 09:32
  • `for (int i = 0; i < grid.Columns.Count; i++)` – LPL Jul 25 '12 at 09:35
  • Yeh, it's getting this line that isn't working `DataGridCellsPresenter presenter = GetVisualChild(rowContainer);` – DanBrum Jul 25 '12 at 09:41
  • I'm saying that the GetCell method above doesn't work because it requires getting the DataGridCells presenter using the DataGridRow which isn't allowed, you have to use the rows index and cast the returned value to a DataGridCells presenter ` DataGridCellsPresenter presenter = (DataGridCellsPResenter) GetVisualChild(row);` like so otherwise it won't compile and this is causing exceptions so I'm not quite sure what you're telling me to do with this method. – DanBrum Jul 25 '12 at 10:42
  • I've edited my answer to show you how to get a list of all DataGridCells. I don't understand what you want with the DataGridCellsPresenter. Sorry. – LPL Jul 25 '12 at 10:55
  • I didn't want DataGridCellsPresenter, you posted the answer with that in it! RE the edit there is no Rows or Columns property on a DataGrid! – DanBrum Jul 25 '12 at 11:26
  • Sorry for the Rows. I corrected this. But [DataGrid.Columns](http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.columns%28v=vs.100%29) exist. Maybe you are not using WPF 4.0 DataGrid? – LPL Jul 25 '12 at 12:01
  • Ah yes there is a columns collection cheers. I am using .NET 3.5, we develop software for use in AutoCAD and we support back to 2009. It's annoying because a lot of WPF doesn't seem to be implemented properly in 3.5. – DanBrum Jul 25 '12 at 12:45
  • That took some doing but we got it! ;) – LPL Jul 25 '12 at 12:50
1

For the sake of convenience (not necessarily performance), you can populate your data (including all cells from all column and rows) from your DataGrid to a single DataTable, which provides functions to help manipulate your data such as iteration, filtering, sorting etc.

// Populate a DataGrid to a DataTable
DataTable dt; 
DataView dv = (DataView) myDataGrid.DataSource;
dt = dv.Table.DataSet.Tables[0];

You can subsequently convert any of a specific column to a collection or list using generics in as short as one line of code. See how-do-you-convert-a-datatable-into-a-generic-list:

List<DataRow> myList = dt.Rows.Cast<DataRow>().ToList();

It saves you from writing loops.

Community
  • 1
  • 1
KMC
  • 19,548
  • 58
  • 164
  • 253
  • Actually you are doing the opposite and you don't answer the question. – LPL Jul 24 '12 at 09:01
  • my understanding of the OP is to store all cells from all rows and columns into a single object that can be conveniently manipulated. A DataTable allows you to pick out any column of data and convert them to collection using generics. Correct me if I'm wrong and why. – KMC Jul 24 '12 at 09:26
  • 1
    I agree that it's better to manipulate/iterate over the data directly and not the DataGridCells. But you transfer data from a DataTable into the DataGrid and I think the OP is asking the other direction. – LPL Jul 24 '12 at 10:16
  • You're right @LPL. My bad for twice not seeing that I was doing the reversed. I have edited my answer. – KMC Jul 24 '12 at 11:05
  • Is this iterating around the Data or actually around the cells themselves? I wish to be able to access the controls themselves. Although if this is around the data it is still useful for me elsewhere. – DanBrum Jul 25 '12 at 09:24
  • DataTable basically converts the DataGrid into a memory structure like database where a cell can be treated like a field that you can select, filter, or iterate by giving it a condition. May you if you can show us how exactly your datagrid looks like and what exactly you want to iterate (iterate a column at a time)? I'll try to work out a sample – KMC Jul 25 '12 at 11:19
  • or if you just want all the cells in a list then LPL's loop just do that – KMC Jul 25 '12 at 11:22
  • I just needed all the cells in the list in order to edit controls in that cell and find the row the cell is in which I have been able to do now. Thanks though, I didn't know about the DataTable as this is the first time I have used a DataGrid so it will definitely be useful for the future. – DanBrum Jul 25 '12 at 12:47
0

To fix the error thrown by the line...

    DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter> 
        (rowContainer);

Add this routine:

private T GetVisualChild<T>(DataGridRow rowContainer)
    {
        throw new NotImplementedException();
    }
Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
Doug
  • 69
  • 1
  • 1
  • 11