我需要知道ListBox
第一次完成渲染的時間,以便我可以將其滾動到頂部以向用戶顯示列表上的第一項。如何知道ListBox在Silverlight中完成呈現的時間?
我有一個使用RichTextBox
在它的DataTemplate
一個ListBox
:
<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>
的ListBox
綁定到ObservableCollection
。
我有一個問題與ListBox
的滾動 - 如果RichTextBox
的高度明顯高於ListBox
用戶將無法滾動到RichTextBox
底部的更大。 ListBox
將跳轉到列表中的下一個項目。滾動條滑塊的高度也會改變。這是因爲RichTextBox
的實際高度僅在實際渲染時計算。當它離開屏幕時,高度恢復爲較小的值(我認爲代碼假定文本可以全部適合單行而不是必須被包裝)。
我跟蹤了這些問題,直到ListBox
使用VirtualisingStackPanel
來繪製項目。當我用簡單的StackPanel
取代那些問題時,這些問題就消失了。
然後,這就產生了我現在的問題,即ListBox
在初始加載時滾動到列表的底部。 ListBox
上的Loaded
和LayoutUpdated
事件發生在數據加載之前。我試着聽出了對視圖模型PropertyChanged
事件時ObservableCollection
被初始化:
void editViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "ListDataSource":
// Try to scroll to the top of the ListBox
break;
}
}
這觸發太早爲好。在此事件被觸發並導致ListBox
滾動到底部之後,列表呈現。
嗯。我對這樣的事情保持警惕 - 特別是因爲列表中可能有很多項目 - 但我會放棄它。 – ChrisF
由於渲染髮生在UI線程中,並且Dispatcher.BeginInvoke將滾動操作推送到UI線程的隊列 - 實際上,無論您的列表有多大都無關緊要。滾動應在其他當前的UI線程指令完成後執行。當然,如果你的集合(或控制/模板的其他部分)被創建爲異步 - 它不會工作。但它是另一種情況。通常情況下,它適用於簡單的場景。 – Kreol
好點 - 雖然列表異步填充.... – ChrisF