Ho bisogno di sapere quando un ListBox
ha terminato il rendering per la prima volta in modo che possa scorrere verso l'alto per presentare all'utente il primo elemento dell'elenco.Come faccio a sapere quando un ListBox ha finito il rendering in Silverlight?
Ho un ListBox
che utilizza RichTextBox
nel suo 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>
Il ListBox
è associato a un ObservableCollection
.
ho avuto un problema con lo scorrimento della ListBox
- se l'altezza del RichTextBox
era maggiore di quello del ListBox
l'utente non può scorrere fino alla fine della RichTextBox
. Lo ListBox
passerebbe alla voce successiva nell'elenco. Anche l'altezza del cursore della barra di scorrimento cambia. Questo perché l'altezza effettiva di RichTextBox
viene calcolata solo quando viene effettivamente visualizzata. Quando è fuori dallo schermo, l'altezza ritorna a un valore inferiore (penso che il codice presuppone che il testo possa adattarsi a una singola riga piuttosto che dover essere avvolto).
Ho rintracciato questi problemi fino all'utilizzo dello ListBox
di un VirtualisingStackPanel
per disegnare gli articoli. Quando l'ho sostituito con un semplice StackPanel
, quei problemi sono andati via.
Questo quindi ha creato il problema che ho ora che è che il ListBox
scorre in fondo alla lista al caricamento iniziale. Gli eventi Loaded
e LayoutUpdated
sullo ListBox
si verificano prima che i dati siano stati caricati. Ho provato ad ascoltare fuori per l'evento PropertyChanged
sul modello vista quando la ObservableCollection
viene inizializzata:
void editViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "ListDataSource":
// Try to scroll to the top of the ListBox
break;
}
}
questo spara troppo presto pure. L'elenco viene reso dopo questo evento viene generato e fa sì che lo ListBox
scorra verso il basso.
Hmm. Sono diffidente nei confronti di cose come questa - specialmente perché potrebbero esserci molti articoli nella lista - ma ci provo. – ChrisF
Poiché il rendering viene eseguito nel thread dell'interfaccia utente e Dispatcher.BeginInvoke trasferisce l'operazione di scorrimento nella coda del thread dell'interfaccia utente: in realtà non importa quanto sia grande l'elenco. Lo scorrimento dovrebbe essere eseguito dopo che sono state fatte altre istruzioni sul thread UI corrente. Naturalmente se la tua raccolta (o altre parti di controllo/modello) viene creata asincrona, non funzionerà.Ma è un altro caso .. Di solito per scenari semplici funziona. – Kreol
Buon punto lì - anche se la lista è popolata in modo asincrono .... – ChrisF