Versión cortaListBox ScrollIntoView cuando se utiliza con CollectionViewSource GroupDescriptions (es decir IsGrouping == true)
quisiera desplazar el elemento ListBox
a la vista cuando se cambia la selección.
Versión larga
Tengo un ListBox
con el ItemsSource
unido a un CollectionViewSource
con un GroupDescription
, de acuerdo con el siguiente ejemplo.
<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 un evento SelectionChanged
en el archivo de un 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 el AnimalsListBox.SelectedItem
en un artículo que actualmente no está visible, me gustaría tenerlo desplazado a la vista. Aquí es donde se vuelve complicado, ya que el ListBox
se está agrupando (la propiedad IsGrouped
es true
) falla la llamada al ScrollIntoView
.
System.Windows.Controls.ListBox
a través de Reflector. Tenga en cuenta base.IsGrouping
en el OnBringItemIntoView
.
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
- Puede alguien explicar por qué lo hace no trabajo cuando usando agrupación?
- El
ItemContainerGenerator.ContainerFromItem
siempre devuelvenull
, aunque su estado indica que se han generado todos los contenedores.
- El
- ¿Cómo puedo lograr el desplazamiento a la vista cuando usando agrupando?
Debe cambiar su respuesta a la correcta, no la de arriba. – Valentein
@Valentein: He cambiado la respuesta marcada. SIN EMBARGO, como los consejos de [crazyarabian] (http://stackoverflow.com/a/7375646/73025) me ayudaron a diagnosticar el problema, sería bueno votar ** ambas ** respuestas si utilizabas mi solución final. – Dennis
Usando .NET 4.5.1 y MVVM puede usar un comportamiento para hacer esto. El comportamiento funciona en ambos escenarios, ya que ya se dispara tarde. – Kelly