Di Wpf (4.0) kotak daftar saya (menggunakan VirtualizingStackPanel) berisi 500 item. Setiap item adalah Tipe khusus
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)
}
Sekarang ketika menggerakkan bilah gulir kotak daftar bolak-balik sehingga visual setiap item dibuat setidaknya sekali penggunaan ram naik hingga 500 Mb setelah beberapa saat dan kemudian - setelah beberapa saat - kembali ke sekitar 250 Mb tetapi tetap pada level ini . Kebocoran memori? Saya pikir keuntungan dari VirtualizingStackPanel adalah visual yang tidak diperlukan/terlihat dibuang...
Pokoknya penggunaan ram ekstrim ini hanya muncul saat menggambar teks menggunakan "DrawText". Menggambar objek lain seperti "DrawEllipse" tidak menghabiskan banyak memori.
Apakah ada cara yang lebih efisien untuk menggambar banyak item teks dibandingkan menggunakan "DrawText" Drawing.Context?
Berikut contoh lengkapnya (buat saja proyek Aplikasi Wpf baru dan ganti kode window1): (Saya tahu ada FlowDocument dan FixedDocument tetapi tidak ada alternatif lain) 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>
Dan 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;
}
}
}