在datagrid中获取行

时间:2011-12-11 14:29:12

标签: c# wpf datagrid row

我试着像这样排:

DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
TextBlock cellContent = dataGrid.Columns[0].GetCellContent(row) as TextBlock;

但我只得到null。还有其他解决方案吗?我做错了什么?

我想从我的手机中获取数据。我的单元格是复选框。

4 个答案:

答案 0 :(得分:2)

这取决于您尝试获取此数据的方式/时间。 WPF更适合通过ItemsSource中绑定的对象访问数据。因此,如果您的ItemsSource是MyObject的List,那么特定的行将是MyObject类型而不是纯DataRow。

如果您通过点击来访问数据,则可以执行以下操作:

var currentItem = myDataGrid.SelectedItem as MyObject;

现在,您拥有当前MyObject的最初预期形式,而不是在网格中挑选。

答案 1 :(得分:1)

获取一个 DataGrid 来处理合适的数据对象以进行操作:

由于 DataGrid 对绑定到数据对象的主体进行操作,因此您需要在 DataTable 之类的东西中跟踪您的数据。

例如,为您的 MainWindow 类初始化一个 DataTable 类型的字段并将其命名为相关内容:

public partial class MainWindow : Window
{
    private DataTable _cars = new DataTable("Cars");

然后在您的构造函数中,在您初始化 Window 组件之后,将 DataGrid.ItemSource 作为数据视图绑定到 DataTable 的集合:

    public MainWindow()
    {
        InitializeComponent();

        dgCars.ItemsSource = _cars.AsDataView();
    }

现在,每当您以编程方式向 _cars 表中添加新行时,它们都会反映在 DataGrid 中,是的!但是,您希望能够从用户界面对数据进行操作,所以让我们深入研究吧!

使用来自用户界面的输入对 DataTable 中的数据进行操作:

当你想对数据进行操作时,你可以从DataGrid里面的item中获取到什么,并使用它们提供的索引从DataTable中移除item,然后重新-应用数据视图。这是总结,但我会更详细地完成示例:

  1. 我们需要遍历每个 DataGrid 项目并在执行我们的逻辑之前检查它是否被选中:

        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                // This is where we do the magic
            }
        }
    
  2. 但是,我们无法从当前用于提供 DataTableDataGrid 中删除项目,否则我们将遇到 IndexOutOfBounds(以及可能的 Enumeration)错误,因此安全起见,我们将使用表的副本进行操作:

        DataTable result = _cars.Copy(); //New in this step
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                result.Rows.RemoveAt(i); //New in this step
            }
        }
    
  3. 再一次,我们会遇到 IndexOutOfBounds 错误,因为我们对数据进行迭代,就好像有 X 的数据量一样,但是每次我们 RemoveAt(i),我们现在都在迭代超过 X-- 的数据量。所以,让我们添加一个计数并跟踪:

        int removed = 0; //New in this step
        DataTable result = _cars.Copy();
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                //Subtracting `removed` new in this step
                result.Rows.RemoveAt(i - removed);
    
                removed++; //New in this step
            }
        }
    
  4. 最后但并非最不重要的一点是,我们会将 _cars 变量指向堆上的 result DataTable 对象,然后重新分配 dgCars.ItemSource = _cars.AsDataView() 以更新我们的 DataGrid (如果有兴趣,可以在我回答的最底部对此进行更复杂的解释)

        int removed = 0;
        DataTable result = _cars.Copy();
        for (int i = 0; i < dgCars.Items.Count; i++)
        {
            if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
            {
                result.Rows.RemoveAt(i - removed);
                removed++;
            }
        }
        _cars = result; //New in this step
        dgCars.ItemSource = _cars.AsDataView(); //New in this step
    

成品:

我们在此构建的示例允许您通过用鼠标选择 DataGrid 上的行,然后单击 Click 值等于 btnRemove_Click 的按钮来从 DataTable 中删除数据。简单的修改和逻辑改变将允许你做同样的添加、编辑等数据,但按照我们最初开始的原则,即对数据对象(在这种情况下,一个ItemsSource)和将该项目设为 DataGridpublic partial class MainWindow : Window { private DataTable _cars = new DataTable("Cars"); public MainWindow() { InitializeComponent(); // THIS WASN'T IN THE BUILD EXAMPLE, BUT AS A BONUS: // We could ALSO use this opportunity to setup static // column headers if we know what they are in advance! _cars.Columns.Add("Year"); _cars.Columns.Add("Make"); _cars.Columns.Add("Model"); dgCars.ItemsSource = _cars.AsDataView(); } private btnRemove_Click(object sender, RoutedEventArgs e) { int removed = 0; DataTable result = _cars.Copy(); for (int i = 0; i < dgCars.Items.Count; i++) { if (dgCars.SelectedItems.Contains(dgCars.Items[i])) { result.Rows.RemoveAt(i - removed); removed++; } } _cars = result; dgCars.ItemSource = _cars.AsDataView(); } }

_cars

-额外阅读-

在前面的第 4 步中,我提到:

<块引用>

最后但并非最不重要的是,我们将 result 变量指向我们的 dgCars.ItemSource = _cars.AsDataView() 堆上的 DataTable 对象,然后重新分配 _cars 以更新我们的 DataGrid

这是因为result_cars都是从实例化的对象,所以它们驻留在堆上。当堆栈上不再有对它们的引用时,堆上的项目被垃圾收集(从内存中删除)。由于 MainWindow 是我们的 btnRemove_Click 的一个字段,并且在 DataTable result 的范围之外继续,当我们将它指向 btnRemove_Click 时,我们保留对该表的引用,并删除我们参考了原表。因此,当 result 完成时,变量 DataTable 被垃圾回收,_cars 用来指向的旧 _cars 被垃圾回收,trt <- rep(LETTERS[1:3],3) qw <- sample(100,9) tr <- sample(100,9) df <- data.frame(trt,qw,tr) df %>% group_by(trt) %>% summarise(mean.mpg = mean(qw, na.rm = TRUE), sd.mpg = sd(qw, na.rm = TRUE), n.mpg = n())%>% mutate(se.mpg = sd.mpg / sqrt(n.mpg), lower.ci.mpg = mean.mpg - qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg, upper.ci.mpg = mean.mpg + qt(1 - (0.05 / 2), n.mpg - 1) * se.mpg) 现在引用我们创建的新 DataTable 对象。

这个答案更详细,其评论也值得一读:https://stackoverflow.com/a/80113/13924556

答案 2 :(得分:0)

也许它对某人有用:

在向 DataGrid(WPF) 添加项目之前,如果您想在将来获得非空的 DataGridRow,要更改一些属性,例如 Background,您需要创建新的 DataGridRow 对象,将您的类分配给 DataGridRow.Item 属性,然后添加到 DataGrid。

像这样:

DataGridRow mRow = new DataGridRow();
mRow.Item = YOUR_DATA_CLASS;
_ = datagrid.Items.Add(mRow);

答案 3 :(得分:-2)

  for(int row =0; row < dg_CountInventory.Rows.Count; row ++) //Loop through each row
    {
        //Provide the Column Index and row as in Loop
        TextBlock b = dg_CountInventory.Columns[1].GetCellContent(dg_CountInventory.Items[row ]) as TextBlock; 
    }

dg_CountInventory是我的网格名称。此代码将遍历所有记录 存在于数据网格和单元/列提供中。#