views:

41

answers:

1

I have to access the value that underlies the active cell of a DataGrid (The cell with the black border around it).

Luckily DataGrid has a lot of properties such as CurrentCell, CurrentItem SelectedCells SelectedItem and SelectedItems seeming to provide me with the data I want.

However I have not figured out how to access the cell in an easy way. I also have changed the …

SelectionMode="Single" SelectionUnit="Cell"

...properties but in the end I had to do something like this:

DataGridCellInfo cellInfo = dataGrid.CurrentCell;
if(null != cellInfo && cellInfo.IsValid){
    object[] array = cellInfo.Item as object[];
    if (null != array && 
        cellInfo.Column.DisplayIndex >= 0 && 
        cellInfo.Column.DisplayIndex < array.Length) {

        object cellValue=array[cellInfo.Column.DisplayIndex];
        if (null != cellValue) {
            // Here we are
        }
    }
}

In my example, the row is built through an object-array containing various object-types. I'm aware that I could execute the binding on the cellInfo.Column (after a cast), however that is not the point. My question is, if I make something really wrong, because I cannot imaging that such a powerful piece of software as DataGrid is, can not provide me the desired value without doing such a lot of coding.

What have I missed or is it really such complicated to get the current cells value.

UPDATE

As Quartermeister explained in his very good answer, there is not a single property to access the cells value and this is has a meaningfull cause. besides, beware of using the DisplayIndex as I do in my example if you let the user rearrange the columns.

+2  A: 

It really is that complicated. The problem is that a DataGridColumn isn't necessarily bound to a single value. A DataGridTemplateColumn, for example, just has a DataTemplate. The template may use multiple values from the row object or even no values at all, so there is no way to usefully return a single value for that cell.

You can be guaranteed to have a single value if the column is a DataGridBoundColumn (such as a DataGridTextColumn). As you said, you can get the value by executing the Binding. For example, you could do something like this (note that this won't work for a binding that uses ElementName or RelativeSource, but you probably won't use those in a DataGridBoundColumn):

var cellInfo = dataGrid.CurrentCell;
if (cellInfo != null)
{
    var column = cellInfo.Column as DataGridBoundColumn;
    if (column != null)
    {
        var element = new FrameworkElement() { DataContext = cellInfo.Item };
        BindingOperations.SetBinding(element, FrameworkElement.TagProperty, column.Binding);
        var cellValue = element.Tag;
    }
}

Note that you probably don't want to use the DisplayIndex property, since that can be changed if the user manually drags the columns to reorder them.

Quartermeister
+1 and Accept: Thanks for this detailed explanation. Now it makes sense to me. By the way, nice way to Execute the binding.
HCL