76

I have a DataGrid, bound to Database table, I need to get the content of selected row in DataGrid, for example, I want to show in MessageBox content of selected row.

Example of DataGrid:

enter image description here

So, if I select the second row, my MessageBox has to show something like: 646 Jim Biology.

Mike
  • 14,010
  • 29
  • 101
  • 161

14 Answers14

163

You can use the SelectedItem property to get the currently selected object, which you can then cast into the correct type. For instance, if your DataGrid is bound to a collection of Customer objects you could do this:

Customer customer = (Customer)myDataGrid.SelectedItem;

Alternatively you can bind SelectedItem to your source class or ViewModel.

<Grid DataContext="MyViewModel">
    <DataGrid ItemsSource="{Binding Path=Customers}"
              SelectedItem="{Binding Path=SelectedCustomer, Mode=TwoWay}"/>
</Grid>
Mike
  • 14,010
  • 29
  • 101
  • 161
Alex McBride
  • 6,881
  • 3
  • 29
  • 30
  • 2
    The second one is exactly what I was looking for. Thanks! – James Sep 11 '14 at 17:44
  • How to get data from the given alternative way? – Shihab Mar 23 '17 at 20:02
  • This second works great, one thing to add that may be helpful for some who are just starting out wpf, like me. In this question we are looking at class Customer. If you do not have a defined class for the row DataRowView works as the data type from System.Data. – Mwspencer Apr 13 '18 at 14:38
20

If you're using the MVVM pattern you can bind a SelectedRecord property of your VM with SelectedItem of the DataGrid, this way you always have the SelectedValue in you VM. Otherwise you should use the SelectedIndex property of the DataGrid.

Gromy
  • 258
  • 1
  • 15
ema
  • 5,668
  • 1
  • 25
  • 31
  • I don't use MVVM, I just begin with WPF/C#/.NET. If I write «ContentDataGrid.SelectedIndex», I get index of selected row in DataGrid, and I need not index, but real value, such as «646 Jim Biology». So how can I get it? – Mike Oct 12 '10 at 10:34
  • You should consider to use a binded object so that you can bind the SelectedItem property of the datagrid. In your case you should try to navigate to the Datagrid properties to find out if it store the selected item property. – ema Oct 12 '10 at 11:24
  • +1. That first sentence was *exactly* what I was looking for! – TarkaDaal Jul 03 '12 at 08:23
  • 1
    SelectedRecord property? I am assuming I would have to set that up myself. Any advice, or a code sample would be great – SoftwareSavant Jun 20 '13 at 19:46
  • @ema , it would be great if you can give code sample. – Mohammed Abrar Ahmed Aug 03 '16 at 13:55
13
public IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
{
    var itemsSource = grid.ItemsSource as IEnumerable;
    if (null == itemsSource) yield return null;
    foreach (var item in itemsSource)
    {
        var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
        if (null != row) yield return row;
    }
}

private void DataGrid_Details_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    try
    {           
        var row_list = GetDataGridRows(DataGrid_Details);
        foreach (DataGridRow single_row in row_lis)
        {
            if (single_row.IsSelected == true)
            {
                MessageBox.Show("the row no."+single_row .GetIndex ().ToString ()+ " is selected!");
            }
        }

    }
    catch { }
}
Bahaa Salaheldin
  • 515
  • 1
  • 7
  • 16
4

This is pretty simple in this DataGrid dg and item class is populated in datagrid and listblock1 is a basic frame.

private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        try
        {
            var row_list = (Item)dg.SelectedItem;
            listblock1.Content = "You Selected: " + row_list.FirstName + " " + row_list.LastName;
        }
        catch { }

    }
    public class Item
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
Ali Zain
  • 610
  • 7
  • 24
4

You can also:

DataRowView row = dataGrid.SelectedItem as DataRowView;
MessageBox.Show(row.Row.ItemArray[1].ToString());
Zeroox
  • 67
  • 5
  • row is null after the first line. What extra code is needed to make this work? (From a design point of view no extra code should be needed but obviously WPF is not well designed) – Paul McCarthy Dec 11 '19 at 10:10
2

Well I will put similar solution that is working fine for me.

 private void DataGrid1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                if (DataGrid1.SelectedItem != null)
                {
                    if (DataGrid1.SelectedItem is YouCustomClass)
                    {
                        var row = (YouCustomClass)DataGrid1.SelectedItem;

                        if (row != null)
                        {
                            // Do something...

                            //  ButtonSaveData.IsEnabled = true;

                            //  LabelName.Content = row.Name;

                        }
                    }
                }
            }
            catch (Exception)
            {
            }
        }
NoWar
  • 36,338
  • 80
  • 323
  • 498
2

@Krytox answer with MVVM

    <DataGrid 
        Grid.Column="1" 
        Grid.Row="1"
        Margin="10" Grid.RowSpan="2"
        ItemsSource="{Binding Data_Table}"
        SelectedItem="{Binding Select_Request, Mode=TwoWay}" SelectionChanged="DataGrid_SelectionChanged"/>//The binding



    #region View Model
    private DataRowView select_request;
    public DataRowView Select_Request
    {
        get { return select_request; }
        set
        {
            select_request = value;
            OnPropertyChanged("Select_Request"); //INotifyPropertyChange
            OnSelect_RequestChange();//do stuff
        }
     }
Mwspencer
  • 1,142
  • 3
  • 18
  • 35
1
private void Fetching_Record_Grid_MouseDoubleClick_1(object sender, MouseButtonEventArgs e)
{
    IInputElement element = e.MouseDevice.DirectlyOver;
    if (element != null && element is FrameworkElement)
    {
        if (((FrameworkElement)element).Parent is DataGridCell)
        {
            var grid = sender as DataGrid;
            if (grid != null && grid.SelectedItems != null && grid.SelectedItems.Count == 1)
            {
                //var rowView = grid.SelectedItem as DataRowView;
                try
                {
                    Station station = (Station)grid.SelectedItem;
                    id_txt.Text =  station.StationID.Trim() ;
                    description_txt.Text =  station.Description.Trim();
                }
                catch
                {

                }
            }
        }
    }
}
Gijs Overvliet
  • 2,643
  • 3
  • 28
  • 35
1

Just discovered this one after i tried Fara's answer but it didn't work on my project. Just drag the column from the Data Sources window, and drop to the Label or TextBox.

f123
  • 382
  • 2
  • 9
1

use your Model class to get row values selected from datagrid like,

        XDocument xmlDoc = XDocument.Load(filepath);

        if (tablet_DG.SelectedValue == null)
        {
            MessageBox.Show("select any record from list..!", "select atleast one record", MessageBoxButton.OKCancel, MessageBoxImage.Warning);
        }
        else
        {
            try
            {
                string tabletID = "";

                 /*here i have used my model class named as TabletMode*/

                var row_list = (TabletModel)tablet_DG.SelectedItem; 
                 tabletID= row_list.TabletID;

                var items = from item in xmlDoc.Descendants("Tablet")
                            where item.Element("TabletID").Value == tabletID
                            select item;

                foreach (var item in items)
                {
                    item.SetElementValue("Instance",row_list.Instance);
                    item.SetElementValue("Database",row_list.Database);
                }

                xmlDoc.Save(filepath);
                MessageBox.Show("Details Updated..!"
                + Environment.NewLine + "TabletId: " +row_list.TabletID + Environment.NewLine
                + "Instance:" + row_list.Instance + Environment.NewLine + "Database:" + row_list.Database, "", MessageBoxButton.YesNoCancel, MessageBoxImage.Information);
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.StackTrace);
            }
        }
0

if I select the second row -

 Dim jason As DataRowView


    jason = dg1.SelectedItem

    noteText.Text = jason.Item(0).ToString()

noteText will be 646. This is VB, but you get it.

deskplace
  • 36
  • 3
0

There are a lot of answers here that probably work in a specific context, but I was simply trying to get the text value of the first cell in a selected row. While the accepted answer here was the closest for me, it still required creating a type and casting the row into that type. I was looking for a simpler solution, and this is what I came up with:

MessageBox.Show(((DataRowView)DataGrid.SelectedItem).Row[0].ToString());

This gives me the first column in the selected row. Hopefully this helps someone else.

nherrmann
  • 147
  • 1
  • 3
  • 10
  • Of course it's a matter of taste, but I personally prefer the accepted answer, since it is based on a standard API and is much more easy-to-read `Customer customer = (Customer)myDataGrid.SelectedItem;` — one line solution, clear and plain. No `(((`, no indexes `Row[0]`, no `ToString()` — too much additional operations to get something API gives you with one command — `SelectedItem`. – Mike Feb 11 '19 at 19:02
  • This is assuming you have a "Customer" class. If your DataGrid is populated from a database query, but you don't have a specific class for the rows in the DataGrid, the accepted answer doesn't work (unless I'm missing something). Perhaps the better solution on my part would be to create such a class, but for something that I don't see myself reusing, that seems superfluous. – nherrmann Feb 12 '19 at 19:53
0

I got something like this:

private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) {

    DataGrid dg = (DataGrid)sender;

    DataRowView selectedRow = dg.SelectedItem as DataRowView;

    if(selectedRow != null) {
        txtXXX.Text = selectedRow["xxx"].ToString();
        txtYYY.Text = selectedRow["yyy"].ToString();
        txtZZZ.Text = selectedRow["zzz"].ToString();
    }

}
Mike
  • 14,010
  • 29
  • 101
  • 161
Guest28512
  • 21
  • 1
0

Your front code:

  • set your model namespace xmlns:viewModel="clr-namespace:CPL3_workstation.MVVM.ModelViews.Tables"
  • set xmlns:d="http://schemas.microsoft.com/expression/blend/2008", because d:DataContext="{d:DesignInstance...}
<DataGrid d:DataContext = "{d:DesignInstance viewModel:TestViewModel, IsDesignTimeCreatable = True}"
            ItemsSource = "{Binding Rows}"
            SelectedItem = "{Binding Selector}">
    <DataGrid.Columns>
        <DataGridTextColumn
            Binding = "{Binding Content1}"
            Header = "Column 1" />
        <DataGridTextColumn
            Binding = "{Binding Content2}"
            Header = "Column 2" />
        <DataGridTextColumn
            Binding = "{Binding Content3}"
            Header = "Column 3" />
    </DataGrid.Columns>
</DataGrid>

Your ViewModel and the Model below:

namespace CPL3_workstation.MVVM.ModelViews.Tables
{
    public class TestViewModel
    {
        public IEnumerable<TestModel> Rows { get; set; }

        public TestModel Selector
        {
            get => selector;
            set => selector = value;
        }

        private TestModel selector;

        public TestViewModel()
        {
            Rows = new List<TestModel>
            {
                new TestModel{ Content1 = "one", Content2 = "two", Content3 = "three" },
                new TestModel{ Content1 = "one", Content2 = "two", Content3 = "three" },
                new TestModel{ Content1 = "one", Content2 = "two", Content3 = "three" },
                new TestModel{ Content1 = "one", Content2 = "two", Content3 = "three" }
            };
        }
    }

    public class TestModel
    {
        public string Content1 { get; set; }
        public string Content2 { get; set; }
        public string Content3 { get; set; }
    }
}

As you can see, the SelectedItem has a binding to the Selector property of the type of your model.

Mike
  • 14,010
  • 29
  • 101
  • 161
  • Thanks for translating the answer, now the worldwide community can benefit from your knowledge and experience. Welcome to SO! – Mike Aug 23 '21 at 13:52