为什么ItemContainerGenerator.ContainerFromIndex()返回null以及如何避免这种行为?

时间:2012-05-14 21:32:29

标签: c# .net wpf datagrid datarow

我正在使用此代码段来分析我在数据网格上选择的行。

for (int i = 0; i < dgDetalle.Items.Count; i++)
{
    DataGridRow row = (DataGridRow)dgDetalle.ItemContainerGenerator.ContainerFromIndex(i);
    FrameworkElement cellContent = dgDetalle.Columns[0].GetCellContent(row);
    // ... code ...
}

循环运行平稳,但在处理某些索引时,第二行会抛出一个空异常。 MSDN的文档说如果'如果项目没有实现',ItemContainerGenerator.ContainerFromIndex(i)将返回null,但这无助于我猜测我如何获得所需的值。

如何扫描所有行?还有其他办法吗?

更新

我正在使用此代码段阅读CheckBox here。所以我不能使用绑定或ItemSource,除非我改变了很多东西。我不能。我正在进行代码维护。

5 个答案:

答案 0 :(得分:17)

试试这个,

DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
        if (row == null)
        {
                          grid.UpdateLayout();
            grid.ScrollIntoView(grid.Items[index]);
            row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
        }

答案 1 :(得分:7)

DataGrid正在虚拟化项目,只有当行在视图中时才会创建相应的行(即容器)。

你可以turn off virtualization(如果你有很多项目,第一次加载非常慢,内存使用率也会更高),或者只是迭代数据并检查数据对象的值“应绑定到数据网格的属性。通常你根本不需要UI元素......

答案 2 :(得分:1)

使用此订阅:

TheListBox.ItemContainerGenerator.StatusChanged += (sender, e) =>
{
  TheListBox.Dispatcher.Invoke(() =>
  {
     var TheOne = TheListBox.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
       if (TheOne != null)
         // Use The One
  });
};

答案 3 :(得分:0)

除了其他答案:控件类的构造函数(页面/窗口/等)中没有项目。

如果要在创建后访问它们,请使用Loaded事件:

public partial class MyUserControl : UserControl
{
    public MyUserControl(int[] values)
    {
        InitializeComponent();

        this.MyItemsControl.ItemsSource = values;

        Loaded += (s, e) =>
        {
            for (int i = 0; i < this.MyItemsControl.Items.Count; ++i)
            {
                // this.MyItemsControl.ItemContainerGenerator.ContainerFromIndex(i)
            }
        };
    }
}

答案 4 :(得分:0)

在我的情况下,grid.UpdateLayout();没有帮助,我需要一个DoEvents()

    DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);

    if (row == null)
    {

        WPFTools.DoEvents();

        grid.ScrollIntoView(grid.Items[index]);
        row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index);
    }


    /// <summary>
    /// WPF DoEvents
    /// Source: https://stackoverflow.com/a/11899439/1574221
    /// </summary>
    public static void DoEvents()
    {
        var frame = new DispatcherFrame();

        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
            new DispatcherOperationCallback(
                delegate (object f)
                {
                    ((DispatcherFrame)f).Continue = false;
                    return null;
                }), frame);

        Dispatcher.PushFrame(frame);
    }