【问题标题】:TreeViewItem.ItemContainerGenerator return null after change ItemsSource更改 ItemsSource 后 TreeViewItem.ItemContainerGenerator 返回 null
【发布时间】:2017-03-07 11:36:41
【问题描述】:

在 TreeViewItem_OnExpanded 事件中,我有以下代码。

var expandedTreeViewItem = e.OriginalSource as TreeViewItem;
var child = expandedTreeViewItem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
expandedTreeViewItem.ItemsSource = // Update ItemsSource
var child = expandedTreeViewItem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;

在更改展开树视图项的ItemSource之前获取child没有问题,但是在更改ItemSource之后,child将为null。

ContainerFromItem(item) 中的item 相同,并且在更改ItemSource 之前和之后都存在。代码的其他部分正常工作。在 ItemSource 更改后,我该怎么做才能获取元素?

TreeViewItem_OnExpanded 事件代码

private void TreeViewItem_OnExpanded(object sender, RoutedEventArgs e)
    {
        var expandedTreeViewItem = e.OriginalSource as TreeViewItem;

        var directoryInfo = expandedTreeViewItem?.Items[0] as DirectoryInfoModel;

        if (expandedTreeViewItem == null || directoryInfo?.HasChild == false) return;

        _folderExplorerViewModel.GetDirectories(directoryInfo?.DirectoryInfo, directoryInfo?.SubDirectoriesCollection);

        expandedTreeViewItem.ItemsSource = directoryInfo?.SubDirectoriesCollection;

        var expandedItemHeader = expandedTreeViewItem?.Template.FindName("PART_Header", expandedTreeViewItem) as ContentPresenter;
        var expandedItemCheckBox = expandedItemHeader?.ContentTemplate.FindName("CheckBoxFolderItem", expandedItemHeader) as CheckBox;

        foreach (var item in expandedTreeViewItem.Items)
        {
            var childItem = expandedTreeViewItem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            var childHeader = childItem?.Template.FindName("PART_Header", childItem) as ContentPresenter;
            var childCheckBox = childHeader?.ContentTemplate.FindName("CheckBoxFolderItem", childHeader) as CheckBox;

            if (childCheckBox != null && expandedItemCheckBox != null)
            {
                childCheckBox.IsChecked = expandedItemCheckBox.IsChecked;
            }
        }
    }

当我在 ItemesSource 更改后使用它时,childItem 始终为 null。但在此之前,它可以工作。

非常感谢。

【问题讨论】:

  • 这也可能是as 的结果。您能否检查expandedTreeViewItem.ItemContainerGenerator.ContainerFromItem(item) 本身是否也返回null?万一此调用返回ContentPresenter(而不是TreeViewItem),通过as 进行转换将返回null
  • @dotNET 你的意思是替换 ItemSource 后 TreeView 将不再使用 TreeViewItems 作为项目容器?
  • @Parham 你确定item 真的是新ItemsSource 集合的一个元素吗?
  • @dotNET 当我使用 ItemContainerGenerator.ContainerFromIte‌​m(item) 后总是返回 null,无论是强制转换还是不强制转换。感谢您的回复。
  • @Clemens 是的,我确定。因为在调试模式下我可以看到项目的详细信息,一切正常。但是只是 ItemContainerGenerator 返回 null 就在我在 ItemSource 更改后使用它的时候!感谢回复

标签: wpf itemsource


【解决方案1】:

我找到了答案here。直到 TreeViewItem_OnExpanded 事件未完成其工作,UI 中尚未创建新项目,因此 ItemContainerGenerator 返回 null。我在它的类中通用了expandedTreeViewItem,并为每个展开的树视图项目添加了LayoutUpdated事件处理程序,然后在LayoutUpdated事件中,我可以访问由ItemSource添加的新项目。我不知道这是否是一种标准方式,但现在它可以在没有任何返回 null 的情况下工作。

private TreeViewItem _expandedTreeViewItem;

    private void TreeViewItem_OnExpanded(object sender, RoutedEventArgs e)
        {
           _expandedTreeViewItem = e.OriginalSource as TreeViewItem;

        var directoryInfo = _expandedTreeViewItem?.Items[0] as DirectoryInfoModel;

        if (_expandedTreeViewItem == null || directoryInfo?.HasChild == false) return;

        _folderExplorerViewModel.GetDirectories(directoryInfo?.DirectoryInfo, directoryInfo?.SubDirectoriesCollection);

        _expandedTreeViewItem.ItemsSource = directoryInfo?.SubDirectoriesCollection;

        _expandedTreeViewItem.LayoutUpdated += ExpandedTreeViewItem_OnLayoutUpdated;      
 }

private void ExpandedTreeViewItem_OnLayoutUpdated(object sender, EventArgs e)
        {
            var expandedItemHeader = _expandedTreeViewItem?.Template.FindName("PART_Header", _expandedTreeViewItem) as ContentPresenter;
            var expandedItemCheckBox = header?.ContentTemplate.FindName("CheckBoxFolderItem", header) as CheckBox;

        foreach (var item in _expandedTreeViewItem.Items)
        {
            var childItem = _expandedTreeViewItem.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            var childHeader = childItem?.Template.FindName("PART_Header", childItem) as ContentPresenter;
            var childCheckBox = childHeader?.ContentTemplate.FindName("CheckBoxFolderItem", childHeader) as CheckBox;

            if (childCheckBox != null && expandedItemCheckBox != null)
            {
                childCheckBox.IsChecked = expandedItemCheckBox.IsChecked;
            }
        }
}

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2015-12-28
    • 2019-05-24
    • 2014-08-17
    • 1970-01-01
    • 2011-02-17
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多