Scroll through a new item in the ItemsControl view

I have an ItemsControl associated with binding to an ObservableCollection . I have this method in code, after which a new model is added to the list. Then I would like to scroll through the new item (at the bottom of the list).

I think the size of the ItemsControl is not yet updated when I request the size, since ActualHeight before and after adding the model is the same. The effect of this code is to scroll to a point slightly larger than the new element.

How do I know what the new ActualHeight will be?

Here is my code:

  ViewModel.CreateNewChapter(); var height = DocumentElements.ActualHeight; var width = DocumentElements.ActualWidth; DocumentElements.BringIntoView(new Rect(0, height - 1, width, 1)); 
+7
data-binding wpf datatemplate itemscontrol
source share
1 answer

I think you need to call BringIntoView in the elements container, and not in the ItemsControl element itself:

 var container = DocumentElements.ItemContainerGenerator.ContainerFromItem(model) as FrameworkElement; if (container != null) container.BringIntoView(); 

EDIT: Actually this does not work, because at the moment the item container has not yet been generated ... Perhaps you could handle the StatusChanged event for ItemContainerGenerator . I tried the following code:

 public static class ItemsControlExtensions { public static void BringItemIntoView(this ItemsControl itemsControl, object item) { var generator = itemsControl.ItemContainerGenerator; if (!TryBringContainerIntoView(generator, item)) { EventHandler handler = null; handler = (sender, e) => { switch (generator.Status) { case GeneratorStatus.ContainersGenerated: TryBringContainerIntoView(generator, item); break; case GeneratorStatus.Error: generator.StatusChanged -= handler; break; case GeneratorStatus.GeneratingContainers: return; case GeneratorStatus.NotStarted: return; default: break; } }; generator.StatusChanged += handler; } } private static bool TryBringContainerIntoView(ItemContainerGenerator generator, object item) { var container = generator.ContainerFromItem(item) as FrameworkElement; if (container != null) { container.BringIntoView(); return true; } return false; } } 

However, it doesn’t work either ... for some reason, ContainerFromItem still returns null after changing state to ContainersGenerated , and I have no idea why: S


EDIT: OK, now I understand ... it was due to virtualization: containers are only generated when they should be displayed, so containers are not created for hidden elements. If you disable virtualization for ItemsControl ( VirtualizingStackPanel.IsVirtualizing="False" ), the solution above works fine.

+5
source share

All Articles