0

In TreeViewItem_OnExpanded event I have below codes.

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;

There is no problem when I get the child before change the ItemSource of expanded tree view item, but after change the ItemSource, child will be null.

The item in ContainerFromItem(item) is same and exist before and after changing ItemSource. The other parts of code works properly. What can I do to get the element after ItemSource changed?

TreeViewItem_OnExpanded event codes

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;
            }
        }
    }

childItem is always null when I use it after ItemesSource changed. But before that, it works.

Thanks a lot.

Parham.D
  • 1,158
  • 2
  • 12
  • 31
  • This could be the result of `as` too. Can you check if `expandedTreeViewItem.ItemContainerGenerator.ContainerFromItem(item)` itself is also returning `null`? Just in case this call returns a `ContentPresenter` (and not a `TreeViewItem`), casting it through `as` will return `null`. – dotNET Mar 07 '17 at 11:39
  • @dotNET You mean that after replacing the ItemSource a TreeView would no longer use TreeViewItems as item containers? – Clemens Mar 07 '17 at 11:40
  • @Parham Are you sure that `item` is really an element of the new ItemsSource collection? – Clemens Mar 07 '17 at 11:41
  • @dotNET when I use ItemContainerGenerator.ContainerFromIte‌​m(item) after always return null, with casting or without casting. Thanks for reply. – Parham.D Mar 07 '17 at 17:24
  • @Clemens Yes, I am sure. Because in debug mode I can see the details of the items, and everything is OK. But simply ItemContainerGenerator return null Just when I use it after ItemSource changing! Thanks for reply – Parham.D Mar 07 '17 at 17:28
  • Please provide a code sample that clearly demonstrates that the very same item is still in the Items collection of the TreeView after you have set its ItemsSource property to a new value. The information you have provided is not enough to reproduce your issue: http://stackoverflow.com/help/mcve – mm8 Mar 07 '17 at 19:14
  • @mm8 I put more codes of TreeViewItem_OnExpanded event. Thanks – Parham.D Mar 08 '17 at 06:38

1 Answers1

0

I found the answer here. Until TreeViewItem_OnExpanded event not finished its job, new items have not been created in UI, so ItemContainerGenerator return null. I made expandedTreeViewItem general in its class and added LayoutUpdated event handler for each expanded tree view item, then in the LayoutUpdated event, I have access to new items added by ItemSource. I don't know if it is a standard way or not, but now it's works without any returning 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;
            }
        }
}
Parham.D
  • 1,158
  • 2
  • 12
  • 31