在 DataGrid WPF 中获取选定的行项

Posted

技术标签:

【中文标题】在 DataGrid WPF 中获取选定的行项【英文标题】:Get selected row item in DataGrid WPF 【发布时间】:2011-04-24 05:41:06 【问题描述】:

我有一个DataGrid,绑定到数据库表,我需要在DataGrid中获取选中行的内容,例如我想在MessageBox中显示选中行的内容。

DataGrid 的示例:

所以,如果我选择第二行,我的 MessageBox 必须显示类似:646 Jim Biology

【问题讨论】:

【参考方案1】:

你的前台代码:

设置你的模型命名空间xmlns:viewModel="clr-namespace:CPL3_workstation.MVVM.ModelViews.Tables" 设置xmlns:d="http://schemas.microsoft.com/expression/blend/2008",因为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="Столбец 1" />
        <DataGridTextColumn
            Binding="Binding Content2"
            Header="Столбец 2" />
        <DataGridTextColumn
            Binding="Binding Content3"
            Header="Столбец 3" />
    </DataGrid.Columns>
</DataGrid>

您的ViewModel 和下面的Model

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; 
    

如您所见,SelectedItem 绑定到模型类型的 Selector 属性。

【讨论】:

感谢您翻译答案,现在全球社区可以从您的知识和经验中受益。欢迎来到 SO!【参考方案2】:

我得到了这样的东西:

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();
    


【讨论】:

【参考方案3】:

您可以使用SelectedItem 属性来获取当前选定的对象,然后您可以将其转换为正确的类型。例如,如果您的 DataGrid 绑定到 Customer 对象的集合,您可以这样做:

Customer customer = (Customer)myDataGrid.SelectedItem;

或者,您可以将SelectedItem 绑定到您的源类或ViewModel

<Grid DataContext="MyViewModel">
    <DataGrid ItemsSource="Binding Path=Customers"
              SelectedItem="Binding Path=SelectedCustomer, Mode=TwoWay"/>
</Grid>

【讨论】:

第二个正是我想要的。谢谢! 如何从给定的替代方式获取数据? 第二个效果很好,补充一点可能对像我这样刚开始使用 wpf 的人有所帮助。在这个问题中,我们正在查看类 Customer。如果您没有为行定义类 DataRowView 作为 System.Data 中的数据类型。【参考方案4】:

这里有很多可能适用于特定上下文的答案,但我只是试图获取所选行中第一个单元格的文本值。虽然这里接受的答案对我来说是最接近的,但它仍然需要创建一个类型并将行转换为该类型。我一直在寻找一个更简单的解决方案,这就是我想出的:

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

这给了我所选行中的第一列。希望这对其他人有帮助。

【讨论】:

当然这是个人喜好问题,但我个人更喜欢接受的答案,因为它基于标准 API 并且更易于阅读 Customer customer = (Customer)myDataGrid.SelectedItem; — 一条线解决方案,清晰和平原。没有(((,没有索引Row[0],没有ToString()——太多的额外操作无法通过一个命令获得API给你的东西——SelectedItem 这是假设您有一个“客户”类。如果您的 DataGrid 是从数据库查询中填充的,但 DataGrid 中的行没有特定的类,则接受的答案不起作用(除非我遗漏了什么)。也许对我来说更好的解决方案是创建这样一个类,但对于我不认为自己重用的东西,这似乎是多余的。【参考方案5】:

@Krytox 用 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
        
     

【讨论】:

【参考方案6】:

您还可以:

DataRowView row = dataGrid.SelectedItem as DataRowView;
MessageBox.Show(row.Row.ItemArray[1].ToString());

【讨论】:

第一行之后的行为空。需要什么额外的代码才能完成这项工作? (从设计的角度来看,不需要额外的代码,但显然 WPF 设计得不好)【参考方案7】:

如果您使用 MVVM 模式,您可以将您的 VM 的 SelectedRecord 属性与 DataGrid 的 SelectedItem 绑定,这样您的 VM 中始终拥有 SelectedValue。 否则,您应该使用 DataGrid 的 SelectedIndex 属性。

【讨论】:

我不使用 MVVM,我只是从 WPF/C#/.NET 开始。如果我写«ContentDataGrid.SelectedIndex»,我会在 DataGrid 中获得所选行的索引,我不需要索引,而是实际值,例如 «646 Jim Biology»。那么我怎样才能得到它呢? 您应该考虑使用绑定对象,以便可以绑定数据网格的 SelectedItem 属性。在您的情况下,您应该尝试导航到 Datagrid 属性以了解它是否存储了选定的项目属性。 +1。第一句话正是我要找的! SelectedRecord 属性?我假设我必须自己设置它。任何建议或代码示例都会很棒 @ema ,如果能提供代码示例就好了。【参考方案8】:

使用您的模型类来获取从数据网格中选择的行值,例如,

        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);
            
        

【讨论】:

【参考方案9】:

在我尝试了 Fara 的答案后才发现这个,但它对我的项目不起作用。只需将列从“数据源”窗口拖放到标签或文本框。

【讨论】:

【参考方案10】:

这在这个 DataGrid dg 中非常简单,项目类填充在 datagrid 中,listblock1 是一个基本框架。

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; 
    

【讨论】:

【参考方案11】:
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
                

                
            
        
    

【讨论】:

【参考方案12】:

如果我选择第二行 -

 Dim jason As DataRowView


    jason = dg1.SelectedItem

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

noteText 将是 646。这是 VB,但你懂的。

【讨论】:

【参考方案13】:

好吧,我会提出适合我的类似解决方案。

 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)
            
            
        

【讨论】:

【参考方案14】:
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  

【讨论】:

以上是关于在 DataGrid WPF 中获取选定的行项的主要内容,如果未能解决你的问题,请参考以下文章

WPF的DataGrid中如何获取当前被选定的行的第一个单元格的值?

WPF Datagrid 样式选定的行

wpf:DataGrid 禁用选定的行样式 - 或行选择

如何在tableview的可变数组中存储多个选定的行项

WPF DataGrid 选定的行样式

如何使用 JavaScript 或 Jquery 选择 GridView 中选定的行项的子项?