【发布时间】:2012-12-05 01:00:22
【问题描述】:
我正在为时间线控件绘制标题。 它看起来像这样:
我每行 0.01 毫秒,所以对于 10 分钟的时间线,我正在查看绘制 60000 行 + 6000 个标签。 这需要一段时间,大约 10 秒。 我想从 UI 线程中卸载它。 我的代码目前是:
private void drawHeader()
{
Header.Children.Clear();
switch (viewLevel)
{
case ViewLevel.MilliSeconds100:
double hWidth = Header.Width;
this.drawHeaderLines(new TimeSpan(0, 0, 0, 0, 10), 100, 5, hWidth);
//Was looking into background worker to off load UI
//backgroundWorker = new BackgroundWorker();
//backgroundWorker.DoWork += delegate(object sender, DoWorkEventArgs args)
// {
// this.drawHeaderLines(new TimeSpan(0, 0, 0, 0, 10), 100, 5, hWidth);
// };
//backgroundWorker.RunWorkerAsync();
break;
}
}
private void drawHeaderLines(TimeSpan timeStep, int majorEveryXLine, int distanceBetweenLines, double headerWidth)
{
var currentTime = new TimeSpan(0, 0, 0, 0, 0);
const int everyXLine100 = 10;
double currentX = 0;
var currentLine = 0;
while (currentX < headerWidth)
{
var l = new Line
{
ToolTip = currentTime.ToString(@"hh\:mm\:ss\.fff"),
StrokeThickness = 1,
X1 = 0,
X2 = 0,
Y1 = 30,
Y2 = 25
};
if (((currentLine % majorEveryXLine) == 0) && currentLine != 0)
{
l.StrokeThickness = 2;
l.Y2 = 15;
var textBlock = new TextBlock
{
Text = l.ToolTip.ToString(),
FontSize = 8,
FontFamily = new FontFamily("Tahoma"),
Foreground = new SolidColorBrush(Color.FromRgb(255, 255, 255))
};
Canvas.SetLeft(textBlock, (currentX - 22));
Canvas.SetTop(textBlock, 0);
Header.Children.Add(textBlock);
}
if ((((currentLine % everyXLine100) == 0) && currentLine != 0)
&& (currentLine % majorEveryXLine) != 0)
{
l.Y2 = 20;
var textBlock = new TextBlock
{
Text = string.Format(".{0}", TimeSpan.Parse(l.ToolTip.ToString()).Milliseconds),
FontSize = 8,
FontFamily = new FontFamily("Tahoma"),
Foreground = new SolidColorBrush(Color.FromRgb(192, 192, 192))
};
Canvas.SetLeft(textBlock, (currentX - 8));
Canvas.SetTop(textBlock, 8);
Header.Children.Add(textBlock);
}
l.Stroke = new SolidColorBrush(Color.FromRgb(255, 255, 255));
Header.Children.Add(l);
Canvas.SetLeft(l, currentX);
currentX += distanceBetweenLines;
currentLine++;
currentTime += timeStep;
}
}
我研究过 BackgroundWorker,但你不能在非 UI 线程上创建 UI 元素。
是否可以在非 UI 线程中执行 drawHeaderLines?
我可以使用数据绑定来绘制线条吗? 这对 UI 响应有帮助吗?
我想我可以使用数据绑定,但样式可能超出了我当前的 WPF 能力(来自 winforms 并试图了解所有这些样式对象是什么并绑定它们)。
谁能提供一个引诱这个的起点?或者谷歌一个可以帮助我入门的教程?
【问题讨论】:
-
我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
-
这是用于屏幕绘画的吗?在 1980 屏幕列上画 60000 条平行线有意义吗?相当多的线可能会被绘制在另一条之上或者将是不可见的。我的意思是,您可以调整绘制线条的数量,以使效果在视觉上仍然可以接受。即使是 1980 行在高清显示器上看起来也像一个块,所以你需要的远比这要少。
-
如果性能是你所追求的(即你正在构建一个序列器或其他东西),你可能想要坚持使用 GDI+,因为这样的东西不完全是 WPF 的之一强项。您将覆盖
OnPaint,使用事件参数的ClipRectangle来获取需要绘制的时间线部分,然后手动计算并绘制该区域内的每个实体。不想强迫您远离 WPF,这只是一个建议。 -
@HighCore:我不敢苟同,因为我是在一台非常慢的笔记本电脑上同时使用 GDI+ 和 WPF 制作塔防游戏的人:D 你的里程可能会有所不同。
-
@HighCore 这是一个误解。 WPF 并不意味着一切都被卸载到 GPU。 XNA 和 WPF 仍然大量使用 CPU。使用 ItemsControl 处理 60k 个项目的重量非常重,而不是画几条线,这对于现代 CPU 来说绝对算不上什么。你用过 CUDA 或 OpenCL 吗?如果是,您无疑会注意到,由于开销,GPU 计算变得比 CPU 计算更高效的边界高得离谱。我创建了两个比较程序。 GDI+ 流畅,WPF 启动时间为 11 秒,窗口大小调整闪烁。
标签: c# wpf data-binding