如何优化Surface ListBox项的样式?

时间:2011-10-08 17:35:32

标签: wpf pixelsense

我在SurfaceListBox中只有15个项目时遇到了性能问题。

使用源绑定到我的viewmodel创建ListBox,我使用ItemContainerStyleSelector,选择要使用的三种样式之一。 但是我仍然有8个ControlTemplates,因为当选择项目时,我有4个状态可以呈现数据项目,加上4个。

StyleSelector非常简单:

public class TaskStyleSelector : StyleSelector
{
    public Style DefaultStyle { get; set; }
    public Style OverdueStyle { get; set; }
    public Style PresentStyle { get; set; }
    public Style CompletedStyle { get; set; }

    public override Style SelectStyle(object item, DependencyObject container)
    {
        var t = item as Sekoia.Karuna.Public.Models.Tasks.Task;
        if (t == null)
            return base.SelectStyle(item, container);

        if (t.Completed)
            return CompletedStyle;
        else if (t.IntervalStartTime <= DateTime.Now && t.IntervalEndTime >= DateTime.Now)
            return PresentStyle;
        else if (t.IntervalEndTime < DateTime.Now)
            return OverdueStyle;
        return DefaultStyle;
    }
}

我的ControlTemplates看起来像这样:

    <ControlTemplate x:Key="defaultTaskTemplate">
            <Border BorderThickness="0, 0, 0, 1" Height="56" BorderBrush="{StaticResource SideBarShadowBrush}" Background="Transparent">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="56"/>
                        <ColumnDefinition Width="130"/>
                        <ColumnDefinition Width="214"/>
                        <ColumnDefinition Width="56"/>
                        <ColumnDefinition Width="56"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Padding="13,16,0,0" Grid.Column="1" Foreground="{StaticResource TextGreyBrush}"><Run Text="{Binding IntervalStartTime, StringFormat=\{0:hh:mm\}}"/><Run Text=" - "/><Run Text="{Binding IntervalEndTime, StringFormat=\{0:hh:mm\}}"/></TextBlock>
                    <TextBlock Padding="13,16,0,0" Grid.Column="2" Foreground="{StaticResource TextGreyBrush}" Text="{Binding Title}"/>
                    <Views:ArrowControl HorizontalAlignment="Center" Width="20" Grid.Column="4" Height="13" VerticalAlignment="Center" ArrowBrushColor="{StaticResource TextGrey}"/>
                    <Views:CheckMarkControl Width="30" Height="30" />
                </Grid>
            </Border>
        </ControlTemplate>

对我来说,这看起来很简单。 但是我的样式看起来像这样:

<Style TargetType="{x:Type ListBoxItem}" x:Key="normalTaskItemStyle" BasedOn="{StaticResource baseTaskStyle}">
            <Setter Property="Template" Value="{StaticResource defaultTaskTemplate}"/>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Template" Value="{StaticResource defaultSelectedTaskTemplate}"/>
                </Trigger>
            </Style.Triggers>
        </Style>

如您所见,我在选择更改时更改模板。

我面临的是当发生对源的实际绑定时,窗口挂起,等待列表框呈现项目。当窗口打开时,我会显示一个“spinner”元素,表示我正在下载内容。一个下载完成,我数据绑定,我看到旋转器在它被删除之前停止。微调器停止向我指示窗口线程因为绑定正在进行而挂起。一旦初始绑定结束,我就可以滚动/平移很好,没有表现出色。

我在网上搜索了有关优化此方案的一些信息,但我似乎无法找到任何相关信息。 我在寻找错误的地方吗?

我还想知道,如果这是一种可以接受的列表生成方式?有没有更简单的方法呢?即避免大量的控制模板和样式?

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

我通常不会在选择项目时更改模板,最好在同一模板中使用可视状态,这可能会避免重新创建一些您在两种状态下重复使用的元素。这个选定的模板不应该导致加载挂起。

我很惊讶你看到只有15件物品有明显的延迟。我没有看到你的模板有任何明显的错误,看起来很简单,但我不知道那些箭头和复选标记控件是什么。您可能希望检查这些控件的xaml(或运行时的可视化树),以确保它们不是不必要的复杂。

您可以尝试一些方法来缩短初始渲染时间:

  1. 使用每个项目中的视觉状态逐步显示内部元素。因此,如果这些箭头或复选标记控件是问题所在,也许您将每个元素从崩溃的元素开始,然后在经过一段时间后使它们可见。

  2. 不要将整个列表绑定到一个,而是绑定到最初为空的列表,然后在调度程序循环中添加每个项目,以允许UI在创建每个容器之间进行响应。