Necesito saber cuando un ListBox
ha terminado de renderizar por primera vez para que pueda desplazarlo hacia arriba para presentar al usuario el primer elemento en la lista.¿Cómo puedo saber cuándo un ListBox ha terminado de renderizarse en Silverlight?
Tengo un ListBox
que utiliza RichTextBox
en que es DataTemplate
:
<DataTemplate x:Key="HelpTextTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
...
<ContentControl>
...
<RichTextBox x:Name="HelpTextContent" Grid.Row="1"
Tag="{Binding Path=HelpObject.Text, Mode=TwoWay}"
TextWrapping="Wrap"
HorizontalAlignment="Stretch"
Margin="0,0,20,0"
Loaded="RichTextBox_Loaded"
ContentChanged="RichTextBox_ContentChanged"
SelectionChanged="RichTextBox_SelectionChanged"/>
...
</ContentControl>
...
</Grid>
</DataTemplate>
El ListBox
se une a un ObservableCollection
.
que tenía un problema con el desplazamiento de la ListBox
- si la altura de la RichTextBox
fue mayor que el de la ListBox
el usuario no podía desplazarse a la parte inferior de la RichTextBox
. El ListBox
pasaría al siguiente elemento de la lista. La altura del control deslizante de la barra de desplazamiento también cambiará. Esto se debe a que la altura real del RichTextBox
solo se calcula cuando se representa en realidad. Cuando está fuera de la pantalla, la altura vuelve a un valor menor (creo que el código supone que el texto puede caber en una sola línea en lugar de tener que ser envuelto).
Seguí estos problemas hasta el uso de VirtualisingStackPanel
para dibujar los elementos. Cuando reemplacé eso con un simple StackPanel
esos problemas desaparecieron.
Esto creó el problema que tengo ahora que es que el ListBox
se desplaza al final de la lista en la carga inicial. Los eventos Loaded
y LayoutUpdated
en ListBox
se producen antes de que se carguen los datos. He intentado escuchar a cabo para el evento PropertyChanged
en el modelo de vista cuando el ObservableCollection
se inicializa:
void editViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "ListDataSource":
// Try to scroll to the top of the ListBox
break;
}
}
este dispara demasiado pronto también. La lista se representa después de este evento se dispara y hace que el ListBox
se desplace hacia la parte inferior.
Hmm. Soy cauteloso con este tipo de cosas, especialmente porque podría haber muchos elementos en la lista, pero lo intentaré. – ChrisF
Dado que el procesamiento tiene lugar en el hilo de la interfaz de usuario, y Dispatcher.BeginInvoke empuja la operación de desplazamiento a la cola del hilo de la interfaz de usuario, en realidad no importa qué tan grande sea su lista. El desplazamiento se debe realizar después de que se realicen otras instrucciones actuales de la secuencia de la interfaz de usuario. Por supuesto, si su colección (u otras partes de control/plantilla) se crea de manera asíncrona, no funcionará.Pero es otro caso ... Por lo general, para escenarios simples, funciona. – Kreol
Buen punto allí, aunque la lista se rellena de forma asíncrona ... – ChrisF