You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF获取DataGridCheckBoxColumn单元格值时遇空引用异常求助

问题:WPF DataGrid遍历到第29行时触发NullReferenceException

尝试遍历WPF应用中DataGrid的每一行,获取DataGridCheckBoxColumn的单元格值,参考示例代码后,运行到第28行正常,但第29行抛出System.NullReferenceException: 'Object reference not set to an instance of an object.'异常。DataGrid实际有约89行数据,代码曾几次正常返回所有值,但现在每次运行都会报错。

相关代码

XAML代码

<DataGrid x:Name="modelDataGrid" Margin="30,85,30,60" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="RefDes" Header="Ref Des" Binding="{Binding RefDes}"/>
        <DataGridTextColumn x:Name="RenPartNumber" Header="Renishaw Part Number" Binding="{Binding RenPartNum}"/>
        <DataGridTextColumn x:Name="FileLocation" Header="File Location" Binding="{Binding FileLocation}"/>
        <DataGridTextColumn x:Name="FileStatus" Header="File Status" Binding="{Binding FileStatus}"/>
        <DataGridTextColumn x:Name="PartClass" Header="Part Class" Binding="{Binding PartClass}"/>
        <DataGridTextColumn x:Name="PartDescription" Header="Part Description" Binding="{Binding PartDescription}"/>
        <DataGridCheckBoxColumn x:Name="IncludeFolder" Header="Include in folder"/>
    </DataGrid.Columns>
</DataGrid>

按钮点击事件C#代码

private void btnGenerateModel_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Make sure you have downloaded the most up to date TFS folder before continuing");

    //Trace.WriteLine(modelDataGrid.Items.Count);

    for (int i = 0; i < modelDataGrid.Items.Count - 1; i++)
    {
        DataGridCell cell = GetCell(i, 6);
        Trace.WriteLine(cell.Content);
    }
}

辅助C#代码

public DataGridCell GetCell(int row, int column)
{
    DataGridRow rowData = GetRow(row);

    Trace.WriteLine(row);
    //Trace.WriteLine(rowData.ToString());
    if (rowData != null)
    {
        DataGridCellsPresenter cellPresenter = GetVisualChild<DataGridCellsPresenter>(rowData);
        DataGridCell cell = (DataGridCell)cellPresenter.ItemContainerGenerator.ContainerFromIndex(column);
        if (cell == null)
        {
            modelDataGrid.ScrollIntoView(rowData, modelDataGrid.Columns[column]);
            cell = (DataGridCell)cellPresenter.ItemContainerGenerator.ContainerFromIndex(column);
        }
        return cell;
    }
    return null;
}

public DataGridRow GetRow(int index)
{
    DataGridRow row = (DataGridRow)modelDataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    
    Trace.WriteLine(row);
    
    if (row == null)
    {
        modelDataGrid.UpdateLayout();
        modelDataGrid.ScrollIntoView(modelDataGrid.Items[index]);
        row = (DataGridRow)modelDataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    }
    return row;
}

public static T GetVisualChild<T>(Visual parent) where T : Visual
{
    T child = default(T);
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

Trace输出(异常出现前最后几行)

System.Windows.Controls.CheckBox Content: IsChecked:False
System.Windows.Controls.DataGridRow
28
System.Windows.Controls.CheckBox Content: IsChecked:False

29

从输出可见,第28行的DataGridRow是有效对象,但第29行的rowData为空。


解决方案

1. 修正循环边界

当前循环条件i < modelDataGrid.Items.Count - 1会跳过最后一行,先改为i < modelDataGrid.Items.Count确保遍历所有行,排除边界计算错误的可能。

2. 提升GetRow方法的可靠性

WPF的ItemContainerGenerator仅为可见行生成容器,滚动后才会生成新行。原方法的ScrollIntoView可能因UI线程延迟未及时生成容器,可添加强制渲染等待:

public DataGridRow GetRow(int index)
{
    if (index < 0 || index >= modelDataGrid.Items.Count)
        return null;

    DataGridRow row = (DataGridRow)modelDataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    
    if (row == null)
    {
        modelDataGrid.ScrollIntoView(modelDataGrid.Items[index]);
        modelDataGrid.UpdateLayout();
        // 强制等待UI渲染完成
        Dispatcher.Invoke(() => {}, DispatcherPriority.Render);
        row = (DataGridRow)modelDataGrid.ItemContainerGenerator.ContainerFromIndex(index);
    }
    return row;
}

3. 采用MVVM绑定方式(推荐)

直接操作可视化树容易受UI容器生成时机影响,更可靠的方式是绑定数据模型:

  • 为数据模型添加bool类型属性(如IsIncludeInFolder)
  • 修改XAML中DataGridCheckBoxColumn的绑定:
    <DataGridCheckBoxColumn x:Name="IncludeFolder" Header="Include in folder" Binding="{Binding IsIncludeInFolder}"/>
    
  • 直接遍历数据源获取值,无需操作UI元素:
    private void btnGenerateModel_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Make sure you have downloaded the most up to date TFS folder before continuing");
    
        foreach (var item in modelDataGrid.Items)
        {
            var dataItem = item as YourDataModelType; // 替换为实际数据模型类型
            if (dataItem != null)
            {
                Trace.WriteLine(dataItem.IsIncludeInFolder);
            }
        }
    }
    

这种方式完全避开可视化树依赖,是WPF的推荐做法,不会出现空引用异常。


内容的提问来源于stack exchange,提问作者ProgramMasher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:21:11