我有一个窗口,其中包含一些具有非常复杂的ItemTemplates的列表视图。性能很糟糕,填充ListView需要200多天,这意味着滚动和过滤根本不是用户友好的。
我开始尝试通过反复试验来优化性能(因为我无法有效地分析PresentationFramework)并发现了一些非常奇怪的事情。例如,通过将上下文菜单从DataTemplate内的标签移动到窗口的静态资源,我获得了显着的性能提升,然后我将其引用为TextArea ContextMenu = {StaticResource ...}(奇怪的是,这样做如果DataTemplate本身是StaticResource,则不提高性能......)
也许这里有人知道更多关于在WPF中编写性能有效的代码并且可以节省一些时间进行调试吗?作为参考,这是我的ItemTemplate现在的样子:
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<Image Source="/HaMusic;component/Images/next_target.png" Height="{Binding Path=FontSize, ElementName=txtBlock}" DockPanel.Dock="Left">
<Image.Visibility>
<MultiBinding Converter="{StaticResource EqualityToVisibilityConverter}">
<Binding Path="DataContext.ServerDataSource.NextItemOverride.UID" RelativeSource="{RelativeSource FindAncestor, AncestorType=UserControl}" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="UID" />
<Binding Path="DataContext.ServerDataSource.NextItemOverrideAction" RelativeSource="{RelativeSource FindAncestor, AncestorType=UserControl}" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Image.Visibility>
</Image>
<TextBlock x:Name="txtBlock" HorizontalAlignment="Stretch" Text="{Binding Item}" Width="Auto">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource EqualityMultiConverter}">
<Binding Path="DataContext.ServerDataSource.CurrentItem.UID" RelativeSource="{RelativeSource FindAncestor, AncestorType=UserControl}" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="UID" />
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="1,0.5" MappingMode="RelativeToBoundingBox" StartPoint="0,0.5">
<GradientStop Offset="-2" Color="#4095FF" />
<GradientStop Offset="-1" Color="White" />
<GradientStop Offset="0" Color="#4095FF" />
<GradientStop Offset="1" Color="White" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Background.(GradientBrush.GradientStops)[0].(GradientStop.Offset)"
From="-2" To="0" Duration="0:0:4" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetProperty="Background.(GradientBrush.GradientStops)[1].(GradientStop.Offset)"
From="-1" To="1" Duration="0:0:4" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetProperty="Background.(GradientBrush.GradientStops)[2].(GradientStop.Offset)"
From="0" To="2" Duration="0:0:4" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetProperty="Background.(GradientBrush.GradientStops)[3].(GradientStop.Offset)"
From="1" To="3" Duration="0:0:4" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Play" Click="MenuItem_PlayItem" />
<MenuItem Header="Play and Return" Click="MenuItem_PlayItemAndReturn" FontWeight="ExtraBold" />
<MenuItem Header="Play Next" Click="MenuItem_PlayItemNext" />
<MenuItem Header="Play Next and Return" Click="MenuItem_PlayItemNextAndReturn" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
带有改进的新代码(有关详细信息,请参阅注释):
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<Image Source="/HaMusic;component/Images/next_target.png" Height="{Binding Path=FontSize, ElementName=txtBlock}" DockPanel.Dock="Left" Visibility="Collapsed"
hmwpf:NextItemImageBehavior.NextItemImage="{Binding DataContext.ServerDataSource.NextItemOverride, ElementName=parent}"
Tag="{Binding DataContext.ServerDataSource, ElementName=parent}"/>
<TextBlock x:Name="txtBlock" HorizontalAlignment="Stretch" Width="Auto"
Text="{Binding Item}"
ContextMenu="{StaticResource contextMenu}"
hmwpf:AnimatedCurrentItemBehavior.AnimatedCurrentItem="{Binding DataContext.ServerDataSource.CurrentItem, ElementName=parent}" />
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
(AnimatedCurrentItem和NextItemImage是附加属性,实现了与多绑定完全相同的逻辑,但是在C#代码中而不是在XAML中)
即使在所有这些变化之后,我仍然比仅渲染纯文本块慢100%,因为看似没有理由(因为在我的测试环境中,图像和背景特殊内容都是不可见的/没有发生)。我认为绑定本身在框架上非常困难,但是当我为随机事物添加更多绑定来测试它时,它不会变得更慢......