Группа Dirty Rects
У меня довольно простой прокручиваемый пользовательский интерфейс календаря:
![enter image description here]()
Но время от времени календарь мигает во время прокрутки. Я просмотрел WPF Performance Suite и заметил, что существует значительное количество Dirty Rect (около 400):
![enter image description here]()
Разметка календаря - это ItemControl, которая связывает дни (привязаны только видимые дни). Похоже, WPF перерисовывает изо дня в день (так почему так много грязных прямоугольников для такого простого пользовательского интерфейса). Я думал, может быть, есть способ сказать WPF не перерисовывать много маленьких прямоугольников, но перерисовать весь элемент ItemsControl сразу (аналогично тому, что Double Buffering делал во все хорошие дни WinForms).
Р. 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>
Ответы
Ответ 1
Я бы добавил в список комментариев, но у меня недостаточно репутации, чтобы сделать это. Еще одна возможная причина, по которой вы можете видеть мигание, связана с замедлением производительности пользовательского интерфейса, вызванным GC. В зависимости от того, как работает ваш код (только часть его размещена), вы можете создавать и сиротировать множество объектов, которые в конечном итоге могут привести к сбою GC и могут вызвать небольшое замедление в пользовательском интерфейсе. Вы должны убедиться, что это происходит, запустив perfmon и посмотрев, запускается ли GC каждый раз, когда пользовательский интерфейс мигает.
Я подумал, что я должен упомянуть об этой возможности, так как это, похоже, не рассматривалось, и это то, что можно протестировать при запуске трассировки вызовов GC во время работы вашего приложения.
Ответ 2
Это не ответ, но это предложение. Я думал, может быть, поскольку xaml внутри будет повторяться столько раз, сколько есть в вашей коллекции Days, это улучшает рендеринг, если мы будем иметь как можно более минимальное кодирование.
- Переместить стили для Border в статический ресурс BorderStyle
- Измените Ярлык на Текстовый блок (у ярлыка есть некоторая смешная предварительная обработка. ex: Удалить _ подчеркивание)
- Поскольку связано только одно свойство, мы можем вынести MultiBinding и установить простую привязку
-
Вы использовали конвертер для рамки Фон. Вы можете создать свойство в Дата, которое возвращает цвет на основе 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>
Как и при изменении SQL-запроса, при изменении плана запроса и его оптимизации эти изменения могут улучшить план рендеринга WPF:)
Ответ 3
Здесь причина перерисовки может быть вызвана изменением уведомления об нежелательном свойстве из кода для коллекции Дни. Это может привести к перезаписи всего списка, что приведет к миганию.
Попробуйте использовать визуальный студийный профайлер, чтобы сузить причину и, следовательно, решить ее.
Профилер доступен в премиальных и конечных версиях студии VS.