ใน 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)
}
ตอนนี้เมื่อย้ายแถบเลื่อนของกล่องรายการไปมาเพื่อให้วิชวลของทุกรายการถูกสร้างขึ้นอย่างน้อยหนึ่งครั้งการใช้งาน ram สูงถึง 500 Mb หลังจากนั้นไม่นาน - หลังจากนั้นไม่นาน - กลับไปที่ประมาณ 250 Mb แต่ยังคงอยู่ที่ระดับนี้ . หน่วยความจำรั่ว? ฉันคิดว่าข้อดีของ VirtualizingStackPanel คือภาพที่ไม่จำเป็น/มองเห็นได้จะถูกกำจัดไป...
อย่างไรก็ตาม การใช้ RAM ที่รุนแรงนี้จะปรากฏเฉพาะเมื่อวาดข้อความโดยใช้ "DrawText" เท่านั้น การวาดวัตถุอื่นๆ เช่น "DrawEllipse" ไม่ใช้หน่วยความจำมากนัก
มีวิธีที่มีประสิทธิภาพในการวาดรายการข้อความจำนวนมากมากกว่าการใช้ "DrawText" ของ Drawing.Context หรือไม่
นี่คือตัวอย่างที่สมบูรณ์ (เพียงสร้างโครงการ Wpf Application ใหม่และแทนที่โค้ด 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;
}
}
}