我尝试像这样获取行:
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
TextBlock cellContent = dataGrid.Columns[0].GetCellContent(row) as TextBlock;
但是我只得到了null
。还有其他解决方案吗?我做错了什么吗?
我想从我的单元格中获取数据。我的单元格是复选框。
我尝试像这样获取行:
DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i);
TextBlock cellContent = dataGrid.Columns[0].GetCellContent(row) as TextBlock;
但是我只得到了null
。还有其他解决方案吗?我做错了什么吗?
我想从我的单元格中获取数据。我的单元格是复选框。
var currentItem = myDataGrid.SelectedItem as MyObject;
DataGridRow mRow = new DataGridRow();
mRow.Item = YOUR_DATA_CLASS;
_ = datagrid.Items.Add(mRow);
DataGrid
接受适当的数据对象以进行操作:由于 DataGrid
的工作原理是绑定到数据对象,因此您需要将数据保存在类似于 DataTable
的东西中。
例如,为您的 MainWindow 类初始化一个类型为 DataTable 的字段,并给它命名一个相关的名称:
public partial class MainWindow : Window
{
private DataTable _cars = new DataTable("Cars");
然后在你的构造函数中,在初始化窗口组件之后,将 DataGrid.ItemSource
绑定到 DataTable 的集合作为数据视图:
public MainWindow()
{
InitializeComponent();
dgCars.ItemsSource = _cars.AsDataView();
}
_cars
表添加新行,它们都将反映在 DataGrid
中,耶!然而,您希望能够从用户界面操作数据,所以让我们深入探讨一下!
DataTable
中的数据:当您想要操作数据时,您可以获取从 DataGrid
内部选择的项目,并使用它们提供的索引从 DataTable
中删除项目,然后重新应用 DataView。这是摘要,但我会详细介绍并完成示例:
We need to iterate over each DataGrid
item and check if it is selected before performing our logic:
for (int i = 0; i < dgCars.Items.Count; i++)
{
if (dgCars.SelectedItems.Contains(dgCars.Items[i]))
{
// This is where we do the magic
}
}
HOWEVER, we can't remove items from the DataTable
that is currently being used to supply the DataGrid
or we'll run into IndexOutOfBounds (and possibly Enumeration) errors, so to be safe, we'll use a copy of the table to operate on:
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
}
}
Again, we'll run into IndexOutOfBounds errors, because we are iteration over the data as if there was X
amount of data, but each time we RemoveAt(i), we're now iterating over X--
amount of data. So, let's add a count and keep track:
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
}
}
Last, but not least, we'll point our _cars
variable to our result
DataTable object on the heap and then reassign the dgCars.ItemSource = _cars.AsDataView()
to update our DataGrid (a more complicated explanation on this at the very bottom of my answer, if interested):
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
)并使该项成为DataGrid
的ItemsSource
。public 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
变量指向堆上的result
DataTable 对象,然后重新分配dgCars.ItemSource = _cars.AsDataView()
来更新我们的 DataGrid。
这样做的原因是因为 _cars
和 result
都是从一个类实例化出来的对象,所以它们位于堆上。堆上的项在堆栈上不再有引用时会被垃圾回收(从内存中删除)。由于 _cars
是我们的 MainWindow
的字段,并且继续超出了 btnRemove_Click
的范围,当我们将其指向 DataTable result
时,我们保留了对该表的引用,并且放弃了对原始表的引用。因此,当 btnRemove_Click
完成时,变量 result
被垃圾回收,原来 _cars
指向的旧的 DataTable
被垃圾回收,而 _cars
现在引用我们创建的新 DataTable 对象。
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是我的网格名称。此代码将循环遍历数据网格中提供的所有记录和单元格/列。
DataGrid
没有Rows
属性。 - O. R. Mapper