В Wpf (4.0) мой список (с использованием VirtualizingStackPanel) содержит 500 элементов.Каждый элемент имеет пользовательский тип
class Page : FrameworkElement
...
protected override void OnRender(DrawingContext dc)
{
// Drawing 1000 single characters to different positions
//(formattedText is a static member which is only instantiated once and contains the string "A" or "B"...)
for (int i = 0; i < 1000; i++)
dc.DrawText(formattedText, new Point(....))
// Drawing 1000 ellipses: very fast and low ram usage
for (int i = 0; i < 1000; i++)
dc.DrawEllipse(Brushes.Black, null, new Point(....),10,10)
}
Теперь при перемещении полосы прокрутки списка вперед и назад, чтобы каждый элемент визуального элемента создавался хотя бы раз после того, как объем оперативной памяти увеличился до 500 Мб через некоторое время, а затем- через некоторое время - возвращается примерно к 250 Мб, но остается на этом уровне.Утечка памяти ?Я думал, что преимущество VirtualizingStackPanel заключается в том, что визуальные элементы, которые не нужны / не видны, удаляются ...
В любом случае, это экстремальное использование оперативной памяти появляется только при рисовании текста с использованием DrawText.Рисование других объектов, таких как DrawEllipse, не занимает столько памяти.
Есть ли более эффективный способ рисования многих текстовых элементов, чем использование DrawText в Drawing.Context?
Вот полный пример (просто создайте новое приложение Wpfспроецировать и заменить код window1): (я знаю, что есть FlowDocument и FixedDocument, но они не являются альтернативой) Xaml:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="900" Width="800">
<Grid Background="Black">
<ListBox Name="lb" ScrollViewer.CanContentScroll="True" Background="Black">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
</Window>
И Window1.xaml.cs:
public partial class Window1 : Window
{
readonly ObservableCollection<FrameworkElement> collection = new ObservableCollection<FrameworkElement>();
public Window1()
{
InitializeComponent();
for (int i = 0; i < 500; i++)
{
collection.Add(new Page(){ Width = 500, Height = 800 });
}
lb.ItemsSource = collection;
}
}
public class Page : FrameworkElement
{
static FormattedText formattedText = new FormattedText("A", CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface(new FontFamily("Arial").ToString()),
12,Brushes.Black);
protected override void OnRender(DrawingContext dc)
{
dc.DrawRectangle(Brushes.White, null, new Rect(0, 0, Width, Height));
double yOff = 0;
for (int i = 0; i < 1000; i++) // draw 1000 "A"s
{
dc.DrawText(formattedText, new Point((i % 80) * 5, yOff ));
if (i % 80 == 0) yOff += 10;
}
}
}