Abdulsalam Elsharif
Abdulsalam Elsharif

Reputation: 5101

WPF Datagrid Get Selected Cell Value

I want to get value for selected cell in datagrid , please anyone tell how to do this. i used SelectedCell changed event , how can i do that?

dataGrid1.CurrentCell

Upvotes: 22

Views: 142687

Answers (17)

Sherlock_Holmes
Sherlock_Holmes

Reputation: 109

Private Sub DataGrid1_CurrentCellChanged(sender As Object, e As EventArgs) Handles DataGrid1.CurrentCellChanged
    MsgBox(sender.CurrentColumn.DisplayIndex & " , " & sender.Items.IndexOf(sender.CurrentItem))
End Sub

This will detect the index of row and column of current cell.

Upvotes: 0

Aaron Christiansen
Aaron Christiansen

Reputation: 11807

If you're like me, and you end up here because you're trying to implement copying individual cell values to the clipboard, then it turns out there's an easier way!

The WPF DataGrid natively supports copying to the clipboard. In your DataGrid XAML element, pass the ClipboardCopyMode property as ExcludeHeader (which is probably what you want if you're trying to copy the individual cell):

<DataGrid ...
          ClipboardCopyMode="ExcludeHeader">

Then add a ClipboardContentBinding to each of your columns to describe what data should be copied from the row's data model when copying:

<DataGrid.Columns>
    <DataGridTemplateColumn Header="Full Name" ...
                            ClipboardContentBinding="{Binding FullName}">

By default, this only works with Ctrl+C. If you need to add it to e.g. a context menu, you can invoke the ApplicationCommands.Copy command to perform the copy too.

Upvotes: 0

Fritz Lambach
Fritz Lambach

Reputation: 1

This is my solution to the problem. Only problem left for me with this solution is the posibility of null references.

var Item = ((DataRowView)dataGrid.SelectedCells[0].Item)
               .Row
               .ItemArray[dataGrid.SelectedCells[0].Column.DisplayIndex];

If you just want a value of a fixed cell in a selected row, you could use this code which is somewhat shorter.

var Item = ((DataRowView)dataGrid.SelectedValue).Row.ItemArray[0];

Don't forget to cast the item into the correct type.

Upvotes: 0

jaredlee.dev
jaredlee.dev

Reputation: 45

Mohamed RT had the right idea, and it worked for me. The only thing that seemed to be missing was an explicit cast to TextBlock. By getting the data grid's CurrentColumn.DisplayIndex you are able to define the exact cell that you wish to pull the value of. This also works when the user rearranges the columns. Here is my code:

int columnIndex = yourDataGrid.CurrentColumn.DisplayIndex;
TextBlock targetCell = (TextBlock)yourDataGrid.SelectedCells[columnIndex].Column.GetCellContent(yourDataGrid.SelectedItem);

And to pull out the value of the TextBlock:

MessageBox.Show("Target cell value is: " + targetCell.Text);

Of all the answers I read, this seemed to be the simplest and most robust. Thanks so much Mohamed!

Upvotes: 0

Niko J
Niko J

Reputation: 1

I was to dumb to find the Solution...

For me (VB):

 Dim string= Datagrid.SelectedCells(0).Item(0).ToString

Upvotes: 0

lulitha
lulitha

Reputation: 103

Worked For me

object item = dgwLoadItems.SelectedItem;
string ID = (dgwLoadItems.SelectedCells[0].Column.GetCellContent(item) as TextBlock).Text;
MessageBox.Show(ID);

Upvotes: 3

Mohamed RT
Mohamed RT

Reputation: 315

I was in such situation .. and found This:

int ColumnIndex = DataGrid.CurrentColumn.DisplayIndex;
TextBlock CellContent = DataGrid.SelectedCells[ColumnIndex].Column.GetCellContent(DataGrid.SelectedItem);

And make sure to treat custom columns' templates

Upvotes: 0

Arun kumar
Arun kumar

Reputation: 1

you can also use this function.

 public static void GetGridSelectedView(out string tuid, ref DataGrid dataGrid,string Column)
    {
        try
        {
            // grid selected row values
            var item = dataGrid.SelectedItem as DataRowView;
            if (null == item) tuid = null;
            if (item.DataView.Count > 0)
            {
                tuid =  item.DataView[dataGrid.SelectedIndex][Column].ToString().Trim();
            }
            else { tuid = null; }
        }
        catch (Exception exc) { System.Windows.MessageBox.Show(exc.Message); tuid = null; }
    }

Upvotes: 0

Rajesh Thampi
Rajesh Thampi

Reputation: 481

I'm extending the solution by Rushi to following (which solved the puzzle for me)

var cellInfo = Grid1.SelectedCells[0];
var content = (cellInfo.Column.GetCellContent(cellInfo.Item) as TextBlock).Text;

Upvotes: 10

ΩmegaMan
ΩmegaMan

Reputation: 31576

Ok after doing reverse engineering and a little pixie dust of reflection, one can do this operation on SelectedCells (at any point) to get all (regardless of selected on one row or many rows) the data from one to many selected cells:

MessageBox.Show(

string.Join(", ", myGrid.SelectedCells
                        .Select(cl => cl.Item.GetType()
                                             .GetProperty(cl.Column.SortMemberPath)
                                             .GetValue(cl.Item, null)))

               );

I tried this on text (string) fields only though a DateTime field should return a value the initiate ToString(). Also note that SortMemberPath is not the same as Header so that should always provide the proper property to reflect off of.

<DataGrid ItemsSource="{Binding MyData}"                      
          AutoGenerateColumns="True"
          Name="myGrid"
          IsReadOnly="True"
          SelectionUnit="Cell"
          SelectionMode="Extended">

Upvotes: 2

Drew Sands
Drew Sands

Reputation: 231

When I faced this problem, I approached it like this: I created a DataRowView, grabbed the column index, and then used that in the row's ItemArray

DataRowView dataRow = (DataRowView)dataGrid1.SelectedItem;
int index = dataGrid1.CurrentCell.Column.DisplayIndex;
string cellValue = dataRow.Row.ItemArray[index].ToString();

Upvotes: 21

Ketan Dubey
Ketan Dubey

Reputation: 430

//Xaml Code
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=Date, Converter={StaticResource    dateconverter}, Mode=OneWay}" Header="Date" Width="100"/>
<DataGridTextColumn Binding="{Binding Path=Prescription}" Header="Prescription" Width="900"/>
</DataGrid.Columns>

//C# Code
 DataRowView row = (DataRowView)grid1.SelectedItem;
 MessageBox.Show(row["Prescription"].toString() + " " + row["Date"].toString());

As WPF provides binding in DataGrids, this should be rather transparent. However, the following method only works, if you have used SQLDataAdapter and provided a binding path to your DataGridColoumns. For eg. Let's say the above datagrid is named grid1, which has auto generate columns set to false, and is using binding to bind column names to Headers. In this case, we use the 'row' variable of type 'DataRowView' and store the selected row in it. Now, use your Binding Paths, and reference individual columns of the selected row. Hope this helps! Cheers!

PS: Works if SelectionUnit = 'Row'

Upvotes: 2

Rushi Soni
Rushi Soni

Reputation: 1128

If you are selecting only one cell then get selected cell content like this

var cellInfo = dataGrid1.SelectedCells[0];

var content = cellInfo.Column.GetCellContent(cellInfo.Item);

Here content will be your selected cells value

And if you are selecting multiple cells then you can do it like this

var cellInfos = dataGrid1.SelectedCells;

var list1 = new List<string>();

foreach (DataGridCellInfo cellInfo in cellInfos)
{
    if (cellInfo.IsValid)
    {
        //GetCellContent returns FrameworkElement
        var content= cellInfo.Column.GetCellContent(cellInfo.Item); 

        //Need to add the extra lines of code below to get desired output

        //get the datacontext from FrameworkElement and typecast to DataRowView
        var row = (DataRowView)content.DataContext;

        //ItemArray returns an object array with single element
        object[] obj = row.Row.ItemArray;

        //store the obj array in a list or Arraylist for later use
        list1.Add(obj[0].ToString());
    }
}

Upvotes: 18

Thomas Bailey
Thomas Bailey

Reputation: 301

I struggled with this one for a long time! (Using VB.NET) Basically you get the row index and column index of the selected cell, and then use that to access the value.

Private Sub LineListDataGrid_SelectedCellsChanged(sender As Object, e As SelectedCellsChangedEventArgs) Handles LineListDataGrid.SelectedCellsChanged

    Dim colInd As Integer = LineListDataGrid.CurrentCell.Column.DisplayIndex

    Dim rowInd As Integer = LineListDataGrid.Items.IndexOf(LineListDataGrid.CurrentItem)

    Dim item As String

    Try
        item = LLDB.LineList.Rows(rowInd)(colInd)
    Catch
        Exit Sub
    End Try

End Sub

End Class

Upvotes: 1

Charles Clayton
Charles Clayton

Reputation: 17946

If SelectionUnit="Cell" try this:

    string cellValue = GetSelectedCellValue();

Where:

    public string GetSelectedCellValue()
    {
        DataGridCellInfo cellInfo = MyDataGrid.SelectedCells[0];
        if (cellInfo == null) return null;

        DataGridBoundColumn column = cellInfo.Column as DataGridBoundColumn;
        if (column == null) return null;

        FrameworkElement element = new FrameworkElement() { DataContext = cellInfo.Item };
        BindingOperations.SetBinding(element, TagProperty, column.Binding);

        return element.Tag.ToString();
    }

Seems like it shouldn't be that complicated, I know...

Edit: This doesn't seem to work on DataGridTemplateColumn type columns. You could also try this if your rows are made up of a custom class and you've assigned a sort member path:

    public string GetSelectedCellValue()
    {
        DataGridCellInfo cells = MyDataGrid.SelectedCells[0];

        YourRowClass item = cells.Item as YourRowClass;
        string columnName = cells.Column.SortMemberPath;

        if (item == null || columnName == null) return null;

        object result = item.GetType().GetProperty(columnName).GetValue(item, null);

        if (result == null) return null;

        return result.ToString();
    }

Upvotes: 7

Trikasus
Trikasus

Reputation: 11

These are 2 methods that can be used to take a value from the selected row

    /// <summary>
    /// Take a value from a the selected row of a DataGrid
    /// ATTENTION : The column's index is absolute : if the DataGrid is reorganized by the user,
    /// the index must change
    /// </summary>
    /// <param name="dGrid">The DataGrid where we take the value</param>
    /// <param name="columnIndex">The value's line index</param>
    /// <returns>The value contained in the selected line or an empty string if nothing is selected</returns>
    public static string getDataGridValueAt(DataGrid dGrid, int columnIndex)
    {
        if (dGrid.SelectedItem == null)
            return "";
        string str = dGrid.SelectedItem.ToString(); // Take the selected line
        str = str.Replace("}", "").Trim().Replace("{", "").Trim(); // Delete useless characters
        if (columnIndex < 0 || columnIndex >= str.Split(',').Length) // case where the index can't be used 
            return "";
        str = str.Split(',')[columnIndex].Trim();
        str = str.Split('=')[1].Trim();
        return str;
    }

    /// <summary>
    /// Take a value from a the selected row of a DataGrid
    /// </summary>
    /// <param name="dGrid">The DataGrid where we take the value.</param>
    /// <param name="columnName">The column's name of the searched value. Be careful, the parameter must be the same as the shown on the dataGrid</param>
    /// <returns>The value contained in the selected line or an empty string if nothing is selected or if the column doesn't exist</returns>
    public static string getDataGridValueAt(DataGrid dGrid, string columnName)
    {
        if (dGrid.SelectedItem == null)
            return "";
        for (int i = 0; i < columnName.Length; i++)
            if (columnName.ElementAt(i) == '_')
            {
                columnName = columnName.Insert(i, "_");
                i++;
            }
        string str = dGrid.SelectedItem.ToString(); // Get the selected Line
        str = str.Replace("}", "").Trim().Replace("{", "").Trim(); // Remove useless characters
        for (int i = 0; i < str.Split(',').Length; i++)
            if (str.Split(',')[i].Trim().Split('=')[0].Trim() == columnName) // Check if the searched column exists in the dataGrid.
                return str.Split(',')[i].Trim().Split('=')[1].Trim();
        return str;
    }

Upvotes: 1

Sheridan
Sheridan

Reputation: 69959

Please refer to the DataGrid Class page on MSDN. From that page:

Selection

By default, the entire row is selected when a user clicks a cell in a DataGrid, and a user can select multiple rows. You can set the SelectionMode property to specify whether a user can select cells, full rows, or both. Set the SelectionUnit property to specify whether multiple rows or cells can be selected, or only single rows or cells.

You can get information about the cells that are selected from the SelectedCells property. You can get information about cells for which selection has changed in the SelectedCellsChangedEventArgs of the SelectedCellsChanged event. Call the SelectAllCells or UnselectAllCells methods to programmatically select or unselect all cells. For more information, see Default Keyboard and Mouse Behavior in the DataGrid Control.

I have added links to the relevant properties for you, but I'm out of time now, so I hope you can follow the links to get your solution.

Upvotes: 18

Related Questions