WPF - 具有大量元素的GUI性能

时间:2015-11-16 19:24:18

标签: c# wpf

我有一个窗口,其中包含一些具有非常复杂的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%,因为看似没有理由(因为在我的测试环境中,图像和背景特殊内容都是不可见的/没有发生)。我认为绑定本身在框架上非常困难,但是当我为随机事物添加更多绑定来测试它时,它不会变得更慢......

0 个答案:

没有答案