ListBox ScrollIntoView cuando se usa CollectionViewSource con GroupDescriptions (es decir, IsGrouping == True)

Version cort

Me gustaría desplazar laListBox elemento a la vista cuando se cambia la selección.

Versión larg

Tengo unListBox con elItemsSource vinculado a unaCollectionViewSource con unGroupDescription, según el ejemplo a continuación.

<Window.Resources>
    <CollectionViewSource x:Key="AnimalsView" Source="{Binding Source={StaticResource Animals}, Path=AnimalList}">
        <CollectionViewSource.GroupDescriptions>
            <PropertyGroupDescription PropertyName="Category"/>
        </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>  
</Window.Resources>

<ListBox x:Name="AnimalsListBox"ItemsSource="{Binding Source={StaticResource AnimalsView}}" ItemTemplate="{StaticResource AnimalTemplate}" SelectionChanged="ListBox_SelectionChanged">
    <ListBox.GroupStyle>
        <GroupStyle HeaderTemplate="{StaticResource CategoryTemplate}" />
    </ListBox.GroupStyle>
</ListBox>

Hay unSelectionChanged evento en el archivo de código subyacente.

public List<Animal> Animals { get; set; }

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ListBox control = (ListBox)sender;
    control.ScrollIntoView(control.SelectedItem);
}

Ahora. Si configuro laAnimalsListBox.SelectedItem a un elemento que actualmente no está visible Me gustaría que se desplazara a la vista. Aquí es donde se pone difícil, ya que laListBox es ser grupos (elIsGrouped propiedad estrue) la llamada aScrollIntoView falla.

System.Windows.Controls.ListBox viaReflecto. Nota labase.IsGrouping en elOnBringItemIntoView.

public void ScrollIntoView(object item)
{
    if (base.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
    {
        this.OnBringItemIntoView(item);
    }
    else
    {
        base.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(this.OnBringItemIntoView), item);
    }
}

private object OnBringItemIntoView(object arg)
{
    FrameworkElement element = base.ItemContainerGenerator.ContainerFromItem(arg) as FrameworkElement;
    if (element != null)
    {
        element.BringIntoView();
    }
    else if (!base.IsGrouping && base.Items.Contains(arg))
    {
        VirtualizingPanel itemsHost = base.ItemsHost as VirtualizingPanel;
        if (itemsHost != null)
        {
            itemsHost.BringIndexIntoView(base.Items.IndexOf(arg));
        }
    }
    return null;
}

Preguntas

¿Alguien puede explicar por qué lo hacen trabajo cuandoutilizand agrupación?LosItemContainerGenerator.ContainerFromItem siempre devuelvenull, a pesar de que su estado indica que se han generado todos los contenedores. ¿Cómo puedo lograr el desplazamiento a la vista cuandoutilizand agrupación?

Respuestas a la pregunta(2)

Su respuesta a la pregunta