ItemContainerGenerator.ContainerFromItem()返回null?

Son*_*Boy 33 wpf containers listbox itemssource

我有一些奇怪的行为,我似乎无法解决.当我遍历ListBox.ItemsSource属性中的项目时,我似乎无法获取容器?我期待看到一个ListBoxItem返回,但我只得到null.

有任何想法吗?

这是我正在使用的一些代码:

this.lstResults.ItemsSource.ForEach(t =>
    {
        ListBoxItem lbi = this.lstResults.ItemContainerGenerator.ContainerFromItem(t) as ListBoxItem;

        if (lbi != null)
        {
            this.AddToolTip(lbi);
        }
    });
Run Code Online (Sandbox Code Playgroud)

ItemsSource当前设置为Dictionary并且包含许多KVP.

Phr*_*ert 50

在这个StackOverflow问题中,我发现了一些对我的案例更有效的东西:

在datagrid中获取行

通过在调用ContainerFromItem或ContainerFromIndex之前放入UpdateLayout和ScrollIntoView调用,可以实现DataGrid的那部分,这使得它可以返回ContainerFromItem/ContainerFromIndex的值:

dataGrid.UpdateLayout();
dataGrid.ScrollIntoView(dataGrid.Items[index]);
var row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(index);
Run Code Online (Sandbox Code Playgroud)

如果您不希望DataGrid中的当前位置发生变化,这对您来说可能不是一个好的解决方案,但如果可以,则无需关闭虚拟化即可运行.


Son*_*Boy 15

最后解决了问题...通过添加VirtualizingStackPanel.IsVirtualizing="False"到我的XAML,现在一切都按预期工作.

在缺点方面,我错过了虚拟化的所有性能优势,因此我将负载路由更改为异步,并在加载时将"微调器"添加到我的列表框中...

  • 正如您所说,由于性能下降,不建议关闭虚拟化。我曾经有几千条长行,在关闭虚拟化后消耗了 >1Gb 内存。可怕的。 (2认同)

epo*_*pox 9

object viewItem = list.ItemContainerGenerator.ContainerFromItem(item);
if (viewItem == null)
{
    list.UpdateLayout();
    viewItem = list.ItemContainerGenerator.ContainerFromItem(item);
    Debug.Assert(viewItem != null, "list.ItemContainerGenerator.ContainerFromItem(item) is null, even after UpdateLayout");
}
Run Code Online (Sandbox Code Playgroud)

  • @Gabor 同样,这个答案没有解释任何内容,只是粘贴的代码。它也只是开始使用名为“item”和“list”的变量,而不识别它们是什么。 (5认同)
  • 这对我的情况非常有效!你救了我的一天。;) 在我的例子中,这个问题是在使用 CustomSort 之后发生的,Misa 的解决方案解决了这个问题。 (2认同)
  • 我不认为这有任何问题。该问题询问列表框及其项目。因此,在这种情况下,这两个变量都应该是不言自明的。 (2认同)

H.B*_*.B. 7

使用调试器逐步执行代码,看看是否实际上没有任何as撤销,或者如果-cast是错误的,从而将其转换为null(您可以使用普通的强制转换来获得正确的异常).

经常发生的一个问题是当a ItemsControl虚拟化大多数项目时,任何时间点都不会存在容器.

此外,我不建议直接处理项目容器,而是绑定属性和订阅事件(通过ItemsControl.ItemContainerStyle).


Ami*_*mir 5

使用此订阅:

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