40

I'm trying to get the values of each column of a selected row in a DataGrid. This is what I have:

private void dataGrid1_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    DataGrid dg = sender as DataGrid;
    Console.WriteLine(dg.SelectedCells[0].ToString());
}

But this does not work. If I do a SelectedCells.Count then I get the correct number of columns but I cannot seem to actually get the values of these columns in the selected row. I've tried for quite a while with no luck! Here is my XAML:

<Grid>
    <DataGrid CanUserAddRows="True" AutoGenerateColumns="False" Height="200" HorizontalAlignment="Stretch" Margin="12,12,79,0" Name="dataGrid1" VerticalAlignment="Top" Width="389" DataContext="{Binding}" CanUserResizeColumns="False" CanUserResizeRows="False" HorizontalContentAlignment="Stretch" PreviewMouseDoubleClick="dataGrid1_PreviewMouseDoubleClick" CellEditEnding="dataGrid1_CellEditEnding">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding  Path=UserID}"
                                Header="User ID" Width="SizeToHeader" />
            <DataGridTextColumn Binding="{Binding  Path=UserName}"
                                Header="User ID" Width="SizeToHeader" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

I would ideally like to access the data through doing something like rowData.UserID but I cannot seem to work it out. There are lots of tutorials and help for using DataGridView but I'm not using this.

Dan J
  • 16,319
  • 7
  • 50
  • 82
Prisoner
  • 27,391
  • 11
  • 73
  • 102

9 Answers9

68

UPDATED

To get the selected rows try:

IList rows = dg.SelectedItems;

You should then be able to get to the column value from a row item.

OR

DataRowView row = (DataRowView)dg.SelectedItems[0];

Then:

row["ColumnName"];
Tony Abrams
  • 4,505
  • 3
  • 25
  • 32
  • 1
    I should have mentioned this is WPF and there doesn't seem to be SelectedRows/SelectedRow – Prisoner Feb 25 '11 at 18:57
  • The second option gives me: Unable to cast object of type 'iAdvert_Desktop.User' to type 'System.Data.DataRowView' and I cannot get the first option to work either :/. I'm pretty new to C#. – Prisoner Feb 25 '11 at 19:07
  • You can change the DataRowView to be User. See if that does it. I was unsure what the type was of your items. – Tony Abrams Feb 25 '11 at 19:19
  • 1
    Rather than giving row["columnName"] you can also give row[0] and so one. Thanks – MindRoasterMir Jan 13 '19 at 21:34
  • You can, but I don't recommend it. When someone comes along later and adds a column the indexes break and you're now referencing a different field. That may break in unique, hidden and special ways... At least with a column name if someone changes the name of the column or removes it the app will at least error early and obviously. Upvote for the comment though because it is an option. – Jeff Nov 01 '19 at 16:01
  • @TonyAbrams To me `DataRowView row = (DataRowView)dg.SelectedItems[0];` returns `row` as null. But this [suggestion](https://stackoverflow.com/a/47616178/1232087) works. I've added a button in each row, and I'm using the code in button click event of a row. But it still surprises me why your suggestion did not work while the other suggestion worked. I wonder what could be a reason? – nam Aug 22 '20 at 03:45
8

Solution based on Tonys answer:

        DataGrid dg = sender as DataGrid;
        User row = (User)dg.SelectedItems[0];
        Console.WriteLine(row.UserID);
Prisoner
  • 27,391
  • 11
  • 73
  • 102
  • 1
    old question this , but i changed SelectedItems[0] to SelectedItem... but this helped me alot! :) upvote! – Arrie Mar 05 '15 at 10:21
7

I did something similar but I use binding to get the selected item :

<DataGrid Grid.Row="1" AutoGenerateColumns="False" Name="dataGrid"
          IsReadOnly="True" SelectionMode="Single"
          ItemsSource="{Binding ObservableContactList}" 
          SelectedItem="{Binding SelectedContact}">
  <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Path=Name}" Header="Name"/>
    <DataGridTextColumn Binding="{Binding Path=FamilyName}" Header="FamilyName"/>
    <DataGridTextColumn Binding="{Binding Path=Age}" Header="Age"/>
    <DataGridTextColumn Binding="{Binding Path=Relation}" Header="Relation"/>
    <DataGridTextColumn Binding="{Binding Path=Phone.Display}" Header="Phone"/>
    <DataGridTextColumn Binding="{Binding Path=Address.Display}" Header="Addr"/>
    <DataGridTextColumn Binding="{Binding Path=Mail}" Header="E-mail"/>
  </DataGrid.Columns>
</DataGrid>

So I can access my SelectedContact.Name in my ViewModel.

Philippe Lavoie
  • 2,583
  • 5
  • 25
  • 39
3

DataGrid get selected rows' column values it can be access by below code. Here grid1 is name of Gride.

private void Edit_Click(object sender, RoutedEventArgs e)
{
    DataRowView rowview = grid1.SelectedItem as DataRowView;
    string id = rowview.Row[0].ToString();
}
Prisoner
  • 27,391
  • 11
  • 73
  • 102
  • Probably the easiest way, you can also call it by column names as well string id = rowview.Row["Id"].ToString(); – DmVinny Feb 26 '21 at 18:17
2

After hours of finding ways on how to get the data from the row selected on a WPF DataGrid Control, as I was using MongoDB. I found this post and used Tony's answer. I revised the code to be relevant to my project. Maybe someone can use this to get an idea.

private void selectionChanged(object sender, SelectionChangedEventArgs e)
    {
        facultyData row = (facultyData)facultyDataGrid.SelectedItem;
        facultyID_Textbox.Text = row.facultyID;
        lastName_TextBox.Text = row.lastName;
        firstName_TextBox.Text = row.firstName;
        middleName_TextBox.Text = row.middleName;
        age_TextBox.Text = row.age.ToString();
    }

}

class facultyData
{
    public ObjectId _id { get; set; }
    public string facultyID { get; set; }
    public string acadYear { get; set; }
    public string program { get; set; }   
}
f123
  • 382
  • 2
  • 9
2

I believe the reason there's no straightforward property to access the selected row of a WPF DataGrid is because a DataGrid's selection mode can be set to either the row-level or the cell-level. Therefore, the selection-related properties and events are all written against cell-level selection - you'll always have selected cells regardless of the grid's selection mode, but you aren't guaranteed to have a selected row.

I don't know precisely what you're trying to achieve by handling the CellEditEnding event, but to get the values of all selected cells when you select a row, take a look at handling the SelectedCellsChanged event, instead. Especially note the remarks in that article:

You can handle the SelectedCellsChanged event to be notified when the collection of selected cells is changed. If the selection includes full rows, the Selector.SelectionChanged event is also raised.

You can retrieve the AddedCells and RemovedCells from the SelectedCellsChangedEventArgs in the event handler.

Hope that helps put you on the right track. :)

Dan J
  • 16,319
  • 7
  • 50
  • 82
  • Well, the idea of this piece of code is to allow me to: Click to edit a username, then when ending the edit I want to save the value based on the UserID of the user which is ReadOnly. So I need to get all the cells for a row (well, only UserID and UserName in this instance). – Prisoner Feb 25 '11 at 19:11
1

An easy way that works:

private void dataGrid_SelectedCellsChanged(object sender, SelectedCellsChangedEventArgs e)
{
    foreach (var item in e.AddedCells)
    {
        var col = item.Column as DataGridColumn;
        var fc = col.GetCellContent(item.Item);

        if (fc is CheckBox)
        {
            Debug.WriteLine("Values" + (fc as CheckBox).IsChecked);
        }
        else if(fc is TextBlock)
        {
            Debug.WriteLine("Values" + (fc as TextBlock).Text);
        }
        //// Like this for all available types of cells
    }
}
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
aminescm
  • 11
  • 1
  • I guess this is fine if you have a CheckBox in every one of your cells. Ofcourse in the infinite number of situation where don't... – ouflak Oct 24 '13 at 09:23
0

I used a similar way to solve this problem using the animescm sugestion, indeed we can obtain the specific cells values from a group of selected cells using an auxiliar list:

private void dataGridCase_SelectionChanged(object sender, SelectedCellsChangedEventArgs e)
    {
        foreach (var item in e.AddedCells)
        {
            var col = item.Column as DataGridColumn;
            var fc = col.GetCellContent(item.Item);
            lstTxns.Items.Add((fc as TextBlock).Text);
        }
    }
0

If you are using an SQL query to populate your DataGrid you can do this :

Datagrid fill

Private Sub UserControl_Loaded(sender As Object, e As RoutedEventArgs)
        Dim cmd As SqlCommand
        Dim da As SqlDataAdapter
        Dim dt As DataTable

        cmd = New SqlCommand With {
            .CommandText = "SELECT * FROM temp_rech_dossier_route",
            .Connection = connSQLServer
        }
        da = New SqlDataAdapter(cmd)
        dt = New DataTable("RECH")
        da.Fill(dt)
        DataGridRech.ItemsSource = dt.DefaultView
End Sub

Value diplay

    Private Sub DataGridRech_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles DataGridRech.SelectionChanged
        Dim val As DataRowView
        val = CType(DataGridRech.SelectedItem, DataRowView)
        Console.WriteLine(val.Row.Item("num_dos"))
    End Sub

I know it's in VB.Net but it can be translated into C#. I put this solution here, it might be useful for someone.

Xaalek
  • 168
  • 1
  • 9