I think you need to call BringIntoView
on the item container, not the ItemsControl itself :
var container = DocumentElements.ItemContainerGenerator.ContainerFromItem(model) as FrameworkElement;
if (container != null)
container.BringIntoView();
EDIT: actually this doesn't work, because at this point, the item container hasn't been generated yet... You could probably handle the StatusChanged
event of the 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 the status changes to ContainersGenerated
, and I have no idea why :S
EDIT : OK, I understand now... this was because of the virtualization : the containers are generated only when they need to be displayed, so no containers are generated for hidden items. If you switch virtualization off for the ItemsControl (VirtualizingStackPanel.IsVirtualizing="False"
), the solution above works fine.