Pokud používáme v Silverlight aplikaci kontrol AutoCompleteBox plněný větším množství prvků (např. nad 1000), setkáme se s výkonnostním problémem, kdy první zobrazení dropdown seznamu je velice pomalé. Toto můžeme spravit jednoduchou úpravou ControlTemplate tohoto kontrolu.
Od Silverlight verze 3.0 se v kontrolu ListBox a podobných využívá tzv. UI Virtualization, jedná se o to, že místo klasického StackPanelu, je jako ItemsPanel použit VirtualizingStackPanel, který vytváří pouze zobrazované prvky a ne všechny prvky předaného zdroje. AutoCompleteBox vnitřně také používá ListBox, takže by se měla použít UI virtualizace. Problém je ale v tom, že při jeho prvním otevření není nastavena velikost listu a v takovém případě jsou vytvářeny všechny prvky. To můžeme opravit tím, že listboxu nastavíme vlastnost MaxHeight.
Vlastnost MaxHeight nemusí být nastavena přímo kontrolu listboxu, ale stačí jí nastavit některému panelu (Grid), ve kterém je ListBox umístěn. V našem případě přidáme nastavení MaxHeight=”450” gridu Popup kontrolu, kterým je tvořen DropDown AutoCompleteBoxu (hodnota 450 je maximální velikost, kterou AutoCompleteBox stejně sám nastavuje při otevření dropdownu). Takto upravená část ControlTemplate controlu AutoCompleteBox vypadá takto:
<ControlTemplate TargetType="sdk:AutoCompleteBox">
<Grid Opacity="{TemplateBinding Opacity}">
...
<Popup x:Name="Popup">
<Grid Opacity="{TemplateBinding Opacity}" MaxHeight="450">
<Border x:Name="PopupBorder" BorderThickness="0" Background="#11000000" HorizontalAlignment="Stretch" Opacity="0">
<Border.RenderTransform>
<TranslateTransform X="1" Y="1"/>
</Border.RenderTransform>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0" HorizontalAlignment="Stretch" Opacity="1.0" Padding="0">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFDDDDDD" Offset="0"/>
<GradientStop Color="#AADDDDDD" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform X="-1" Y="-1"/>
</TransformGroup>
</Border.RenderTransform>
<ListBox x:Name="Selector" BorderThickness="0" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ItemTemplate="{TemplateBinding ItemTemplate}" ItemContainerStyle="{TemplateBinding ItemContainerStyle}" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</Border>
</Border>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
Tím je tato chyba opravena. Tuto úpravu je možné aplikovat úplně obecně ve všech použití AutoCompleteBoxu.
Příspěvek je inspirován článkem zde:
http://coreclr.wordpress.com/2009/09/26/silverlight-3-listbox-combobox-and-autocompletebox-performance