Dirty Rects分组

时间:2013-10-28 07:29:26

标签: .net wpf

我有一个非常简单的可滚动日历UI:

enter image description here

但是滚动期间日历会不时闪烁。我查看了WPF Performance Suite并注意到有大量Dirty Rects(大约400):

enter image description here

日历的标记是ItemsControl,它绑定Days(仅限可见天数)。看起来像WPF一天一天地重绘(所以这就是为什么这么简单的用户界面有这么多脏的原因)。我想可能有一种方法可以告诉WPF不要重绘许多小矩形但是一次重绘整个ItemsControl(类似于Double Buffering在WinForms的所有好日子里所做的那样)。

P上。 S. WritableBitmap解决了这个问题,但我希望有一个更好的方法

更新。以下是我在以下情况下切换“显示脏区更新叠加层”选项时的外观:

enter image description here

所以WPF正确找到了脏区。问题是为什么它决定使用这么多脏的重新绘制它。我的猜测是因为天数(白色的一个或两个像素)之间的空间在滚动期间是相同的。

更新2。

以下是日历的标记:

<ItemsControl  Panel.ZIndex="1" Grid.Column="1" 
       ItemsSource="{Binding Days}" 
       VerticalAlignment="Center" 
       HorizontalAlignment="Stretch">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border Margin="1,0,1,0" Padding="0,0,3,0" 
                  CornerRadius="1" Width="28" Height="28" 
                  VerticalAlignment="Top">
                <Border.Background>
                    <MultiBinding Converter="{StaticResource DayOfWeekToColorConverter}">
                        <Binding Path="IsWeekend"/>
                    </MultiBinding>
                </Border.Background>
                <StackPanel>
                    <TextBlock  Style="{StaticResource TextStyle}" 
                          HorizontalAlignment="Center" 
                          VerticalAlignment="Center"/>
                    <Label  Style="{StaticResource LabelStyle}" 
                          Content="{Binding Date.Day}" 
                          HorizontalAlignment="Center" 
                          VerticalAlignment="Center"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

3 个答案:

答案 0 :(得分:1)

我会加入评论列表,但我没有足够的声誉这样做。您可能会看到闪烁的另一个可能原因是由于GC导致的UI性能下降。根据代码的工作方式(只发布其中的一部分),您可能正在创建和孤立许多最终会导致GC触发的对象,并可能导致UI略微减速。您应该能够通过运行perfmon并查看每次UI闪烁时是否触发GC来查看是否是这种情况。

我认为我应该提到这种可能性,因为它似乎没有被考虑过,并且可以在应用程序运行时运行一系列GC调用来测试。

答案 1 :(得分:1)

这不是答案,但这是一个建议。我认为可能是因为 中的xaml会像 Days 集合中的项目一样重复多次,如果编码尽可能小,它会改善渲染效果

  1. 边框的样式移至静态资源 BorderStyle
  2. 标签更改为 TextBlock (标签已完成一些有趣的预处理。例如:删除 _ 下划线)
  3. 由于只有一个属性被绑定,我们可以取出 MultiBinding 并放置简单的绑定
  4. 您已将转换器用于边框背景。您可以在日期中创建一个属性,该属性会根据WeekDay返回颜色。

            <DataTemplate>
                <Border Style="{StaticResource BorderStyle}" Background="{Binding Date.DayBackgroundColor}">
                    <StackPanel>
                        <TextBlock  Style="{StaticResource TextStyle}"/>
                        <TextBlock  Style="{StaticResource LabelStyle}" Text="{Binding Date.Day}" />
                    </StackPanel>
                </Border>
            </DataTemplate>
    
  5. 就像稍微更改SQL查询一样,查询计划发生了变化并进行了优化,这些更改可能会改进WPF的渲染计划:)

答案 2 :(得分:1)

此处重绘的原因可能是由于集合的代码触发了不需要的属性更改通知。这可能导致重新绑定整个列表导致闪烁。

尝试使用visual studio profiler缩小原因,从而解决问题。  Profiler适用于VS studio的高级版和终极版。