我在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”元素,表示我正在下载内容。一个下载完成,我数据绑定,我看到旋转器在它被删除之前停止。微调器停止向我指示窗口线程因为绑定正在进行而挂起。一旦初始绑定结束,我就可以滚动/平移很好,没有表现出色。
我在网上搜索了有关优化此方案的一些信息,但我似乎无法找到任何相关信息。 我在寻找错误的地方吗?
我还想知道,如果这是一种可以接受的列表生成方式?有没有更简单的方法呢?即避免大量的控制模板和样式?
有人可以帮忙吗?
答案 0 :(得分:1)
我通常不会在选择项目时更改模板,最好在同一模板中使用可视状态,这可能会避免重新创建一些您在两种状态下重复使用的元素。这个选定的模板不应该导致加载挂起。
我很惊讶你看到只有15件物品有明显的延迟。我没有看到你的模板有任何明显的错误,看起来很简单,但我不知道那些箭头和复选标记控件是什么。您可能希望检查这些控件的xaml(或运行时的可视化树),以确保它们不是不必要的复杂。
您可以尝试一些方法来缩短初始渲染时间:
使用每个项目中的视觉状态逐步显示内部元素。因此,如果这些箭头或复选标记控件是问题所在,也许您将每个元素从崩溃的元素开始,然后在经过一段时间后使它们可见。
不要将整个列表绑定到一个,而是绑定到最初为空的列表,然后在调度程序循环中添加每个项目,以允许UI在创建每个容器之间进行响应。