in src/StructuredLogViewer/Controls/TreeViewExtensions.cs [85:192]
private static void SelectContainerFromItem<T>(this ItemsControl container, SelectInfo<T> selectInfo, TreeView treeView)
{
var currentItem = selectInfo.Items.First();
var itemContainerGenerator = container.ItemContainerGenerator;
if (itemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
{
// If the item containers haven't been generated yet, attach an event
// and wait for the status to change.
EventHandler selectWhenReadyMethod = null;
selectWhenReadyMethod = (ds, de) =>
{
if (itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
// Stop listening for status changes on this container
itemContainerGenerator.StatusChanged -= selectWhenReadyMethod;
// Attempt to fix https://github.com/KirillOsenkov/MSBuildStructuredLog/issues/453
container.Dispatcher.BeginInvoke((Action)delegate
{
// Search the container for the item chain
SelectContainerFromItem(container, selectInfo, treeView);
}, DispatcherPriority.Render);
}
};
itemContainerGenerator.StatusChanged += selectWhenReadyMethod;
return;
}
Debug.Assert(itemContainerGenerator.Status == GeneratorStatus.ContainersGenerated);
// Compare each item in the container and look for the next item
// in the chain.
foreach (object item in container.Items)
{
var convertedItem = (T)item;
// Compare the converted item with the item in the chain
if ((selectInfo.CompareMethod != null) && selectInfo.CompareMethod(convertedItem, currentItem))
{
// Since the TreeViewItems are in a virtualized panel, the item to be selected may not be realized,
// need to ensure it is brought into view, so it can be selected.
ItemsPresenter itemsPresenter = FindVisualChild<ItemsPresenter>(container);
var containerFromItem = itemContainerGenerator.ContainerFromItem(item) as FrameworkElement;
if (itemsPresenter != null && (containerFromItem == null || !containerFromItem.IsOnScreen(treeView)))
{
int index = container.Items.IndexOf(currentItem);
var child = VisualTreeHelper.GetChild(itemsPresenter, 0);
var virtualizingPanel = child as VirtualizingStackPanel;
if (virtualizingPanel != null)
{
virtualizingPanel.BringIndexIntoViewPublic(index);
}
else
{
if (child is StackPanel stackPanel)
{
if (stackPanel.Children[index] is FrameworkElement frameworkElement)
{
frameworkElement.BringIntoView();
}
}
}
}
var containerParent = (ItemsControl)itemContainerGenerator.ContainerFromItem(item);
if (containerParent == null)
{
return;
}
// Replace with the remaining items in the chain
selectInfo.Items = selectInfo.Items.Skip(1);
// If no items are left in the chain, then we're finished
if (selectInfo.Items.Count() == 0)
{
// Select the last item
if (selectInfo.SelectItem != null)
{
Action action = new Action(() =>
{
selectInfo.SelectItem(containerParent, selectInfo);
});
// Here we dispatch the select action so the TreeViewItem is focused
// and scrolled into view correctly.
container.Dispatcher.BeginInvoke(action, DispatcherPriority.Render);
}
}
else
{
// Request more items and continue the search
if (selectInfo.NeedMoreItems != null)
{
selectInfo.NeedMoreItems(containerParent, selectInfo);
SelectContainerFromItem(containerParent, selectInfo, treeView);
}
}
break;
}
}
}