Как оптимизировать стиль элементов Surface ListBox? - PullRequest
1 голос
/ 08 октября 2011

У меня проблемы с производительностью всего 15 элементов в SurfaceListBox.

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;
    }
}

Мои шаблоны управления выглядят так:

    <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 Ответ

1 голос
/ 12 октября 2011

Обычно я не стал бы беспокоиться об изменении шаблона при выборе элемента, лучше использовать визуальное состояние в одном и том же шаблоне, что, вероятно, позволило бы избежать воссоздания некоторых элементов, которые в противном случае вы бы повторно использовали в обоих состояниях. Этот выбранный шаблон не должен вызывать зависание загрузки.

Я удивлен, что вы видите заметную задержку только с 15 предметами. Я не вижу ничего явно неправильного в вашем шаблоне, это кажется довольно простым, но я не знаю, что находится в этих элементах управления стрелками и галочками. Возможно, вы захотите проверить xaml (или визуальное дерево времени выполнения) этих элементов управления, чтобы убедиться, что они не являются излишне сложными.

Есть пара вещей, которые вы можете попытаться уменьшить начальное время рендеринга:

  1. Используйте визуальные состояния в каждом элементе для постепенного отображения внутренних элементов. Итак, если эти элементы управления стрелками или галочками являются проблемой, возможно, у вас каждый элемент начинается с того, что эти элементы свернуты, а затем делает их видимыми через некоторое время.

  2. Не связывайте весь список за один раз, а связывайте с изначально пустым списком, а затем добавляйте каждый элемент в цикл диспетчера, который позволяет UI реагировать между созданием каждого контейнера.

...