У меня была эта проблема в шаблоне столбца DataGrid
, где я использовал <Canvas><Path /></Canvas>
(в качестве статического ресурса) в VisualBrush
(также в качестве статического ресурса) и использовал его в качестве OpacityMask
за Rectangle
. Всякий раз, когда DataGrid перезагружался, Rectangle
не выпускал VisualBrush
ссылок на OpacityMask
, я использовал инструмент профилирования памяти, чтобы показать, что все объекты VisualBrush
используют большую часть памяти.
Я не понимаю, почему или как это произошло, но я рад, что я не одинок (даже если бы у меня была такая же проблема примерно 6,5 лет спустя ...).
Мой XAML был примерно таким:
<DataGrid.Resources>
<Canvas x:Key="icon" ...>
<Path ... />
</Canvas>
<VisualBrush x:Key="iconBrush" Stretch="Uniform" Visual="{StaticResource icon}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
...
</DataGrid.Columns>
Я читал, что настройка IsFrozen = true
(выполненная с использованием этой техники: https://www.codeproject.com/Tips/72221/Freeze-brushes-directly-in-the-XAML-to-improve-you) поможет решить проблемы с памятью с помощью кистей, однако, похоже, это никак не отразилось. Weird.
Я думал, что поэкспериментирую, и рассуждал, что, если проблема протекала VisualBrush
, я подумал, не имеет ли ее значение StaticResource
, связанное с объектными ссылками, поэтому я изменил его на "принадлежащий" объект вот так:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
>
<VisualBrush Stretch="Uniform" Visual="{StaticResource iconBrush}" />
</Rectangle>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Это исправило проблему! И я до сих пор не знаю почему - интересно, это ошибка в WPF?
В связи с этим я понял, что использование VisualBrush
было излишним, поскольку я рендеринг просто Path
- VisualBrush
стоит дорого, потому что он отображает весь вид WPF - я также узнал от других документация о том, что Path
сама по себе не требуется для рендеринга простых фигур, потому что сама является полными UIElement
и FrameworkElement
- которые являются "более тяжелыми" типами.
Я изменил свой код для сохранения пути в значении PathGeometry
внутри GeometryDrawing
статического ресурса, который загружается в DrawingBrush
:
<GeometryDrawing x:Key="iconDrawing" Brush="Black" Geometry="..." />
<Rectangle
Fill="{Binding Foreground, ElementName=myDataGrid}"
Width="14"
Height="14"
Margin="4"
Visibility="{Binding IconVisibility}"
OpacityMask="{StaticResource iconBrush}"
>
<DrawingBrush Stretch="Uniform" Drawing="{StaticResource iconDrawing}" />
</Rectangle>
Это также сказалось на использовании памяти и, надеюсь, производительности.
В вашем проекте я вижу, что вы не используете информацию о пути в качестве ресурса, но применяется та же техника: загрузите ваш путь в PathGeometry
(точнее, StreamGeometry
объект, который еще быстрее и предназначен для неизменной геометрии) и установите это как Drawing
для DrawingBrush
.