已经使用虚拟化的 Silverlight 组合框性能改进

Silverlight combobox performance improvements already using virtualization

我正在使用组合框来显示带有复选框的项目列表。我面临的问题是打开组合框列表时显示(我猜是渲染)项目列表的性能在增加项目数量时变慢(例如 300 个项目大约需要 3 秒,我需要显示 1000 秒) .

代码如下所示:

MultiSelComboBoxStyle.xaml

    <ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:System="clr-namespace:System;assembly=mscorlib">

    <Style x:Key="CheckBoxListBoxItemStyle" TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <Grid x:Name="RootElement">
                        <!--<CheckBox ClickMode="Press" Content="{Binding Path=Name}" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" />-->
                        <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Text}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="MSMMultiSelComboBoxStyle" TargetType="ComboBox">
        <Setter Property="Padding" Value="6,2,25,2"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="TabNavigation" Value="Once"/>
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ComboBox">
                    <Grid>
                        <Border x:Name="ContentPresenterBorder">
                            <Grid>
                                <ToggleButton x:Name="DropDownToggle" HorizontalAlignment="Stretch" HorizontalContentAlignment="Right" Margin="0" VerticalAlignment="Stretch">
                                    <Path x:Name="BtnArrow" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " HorizontalAlignment="Right" Height="4" Margin="0,0,6,0" Stretch="Uniform" Width="8">
                                        <Path.Fill>
                                            <SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
                                        </Path.Fill>
                                    </Path>
                                </ToggleButton>
                                <ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                    <TextBlock x:Name="tb" Text=" "/>
                                </ContentPresenter>
                            </Grid>
                        </Border>
                        <Rectangle x:Name="DisabledVisualElement" IsHitTestVisible="false" Opacity="0" RadiusY="3" RadiusX="3"/>
                        <Rectangle x:Name="FocusVisualElement" IsHitTestVisible="false" Margin="1" Opacity="0" RadiusY="2" RadiusX="2" StrokeThickness="1"/>
                        <Border x:Name="ValidationErrorElement" BorderThickness="1" CornerRadius="1" Visibility="Collapsed">
                            <ToolTipService.ToolTip>
                                <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" >
                                    <ToolTip.Triggers>
                                        <EventTrigger RoutedEvent="Canvas.Loaded">
                                            <BeginStoryboard>
                                                <Storyboard>
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
                                                        <DiscreteObjectKeyFrame KeyTime="0">
                                                            <DiscreteObjectKeyFrame.Value>
                                                                <System:Boolean>true</System:Boolean>
                                                            </DiscreteObjectKeyFrame.Value>
                                                        </DiscreteObjectKeyFrame>
                                                    </ObjectAnimationUsingKeyFrames>
                                                </Storyboard>
                                            </BeginStoryboard>
                                        </EventTrigger>
                                    </ToolTip.Triggers>
                                </ToolTip>
                            </ToolTipService.ToolTip>
                            <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
                                <Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Margin="1,3,0,0"/>
                                <Path Data="M 0,0 L2,0 L 8,6 L8,8" Margin="1,3,0,0"/>
                            </Grid>
                        </Border>
                        <Popup x:Name="Popup">
                            <Border x:Name="PopupBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" HorizontalAlignment="Stretch" Height="Auto">
                                <Border.Background>
                                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                        <!--<GradientStop Color="#FFFFFFFF" Offset="0"/>
                                        <GradientStop Color="#FFFEFEFE" Offset="1"/>
                                    -->
                                    </LinearGradientBrush>
                                </Border.Background>
                                <ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
                                    <!--<ItemsPresenter/>-->
                                    <ListBox x:Name="lstBox" SelectionMode="Multiple" ItemsSource="{TemplateBinding ItemsSource}" ItemContainerStyle="{StaticResource CheckBoxListBoxItemStyle}" HorizontalAlignment="Stretch" >
                                        <ListBox.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <VirtualizingStackPanel  />
                                            </ItemsPanelTemplate>
                                        </ListBox.ItemsPanel>
                                    </ListBox>
                                </ScrollViewer>
                            </Border>
                        </Popup>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

DeskCombo.xaml

<UserControl x:Class="Apama.UI.Surveillance.Controls.DeskCombo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="28" d:DesignWidth="400">

    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="MultiSelComboBoxStyle.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <ComboBox x:Name="cbDesk"  Grid.Row="0" Grid.Column="0" Style="{StaticResource MSMMultiSelComboBoxStyle}" >
            <ComboBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel />
                </ItemsPanelTemplate>
            </ComboBox.ItemsPanel>
        </ComboBox>
    </Grid>
</UserControl>

这就是我将项目绑定到组合框的方式:

List<Desk> desks = new List<Desk>();

        desks.Add(new Desk() { DeskId = UIConstants.SELECT_ALL_TEXT, DeskName = UIConstants.SELECT_ALL_TEXT, DimDeskId = UIConstants.SELECT_ALL_ID });
        desks.AddRange(data.Desks.Values);

        _items = new StaticDataStore<Desk>(GetItemName, desks, AddAll);
        ComboBoxItems = new ComboBoxDataItemCollection(desks.Select(dk => new ComboBoxDataItem(dk.DimDeskId) { Text = dk.DeskName }));
        ComboBoxItems.Owner = this;

        // Bind
        cbDesk.ItemsSource = ComboBoxItems.ToList();

我做了一些研究,我认为这可能与项目的虚拟化有关,但我将标签包含在样式模板列表框和组合框本身中,但没有看到任何变化。

还有什么我可以检查的吗?任何想法将不胜感激。

一天结束时,我摆脱了 MultiSelComboBoxStyle.xaml 并以这种方式更改了 DeskCombo.xaml:

<UserControl x:Class="Apama.UI.Surveillance.Controls.DeskCombo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="28" d:DesignWidth="400">

<Grid x:Name="LayoutRoot">
    <ComboBox x:Name="cbDesk"  Grid.Row="0" Grid.Column="0" DropDownClosed="hideSelected">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay}" Content="{Binding Text}" />
            </DataTemplate>
        </ComboBox.ItemTemplate>
        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>
    </ComboBox>
</Grid>

我加入了 "hideSelected" 回调,因为我不希望下拉窗口在关闭时显示任何值。该回调就是这样做的:

private void hideSelected(object sender, EventArgs e)
    {
        cbDesk.SelectedItem = null;
    }

由于我对样式的首选是保持网站的外观和感觉,所以我很好地摆脱了 MultiSelComboBoxStyle.xaml。该文件的大部分功能是包含复选框项目并在组合框中隐藏值 "selected" ,但该代码中的某些东西搞砸了性能。