jpi*_*olo 5 c# data-binding wpf
我正在绘制时间轴控件的标题.它看起来像这样:

我每行走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;
}
}
Run Code Online (Sandbox Code Playgroud)
我查看了BackgroundWorker,除了你不能在非UI线程上创建UI元素.
是否有可能在非UI线程中执行drawHeaderLines?
我可以使用数据绑定来绘制线条吗?这有助于UI响应吗?
我想我可以使用数据绑定,但是Styling可能超出了我目前的WPF能力(来自winforms并试图了解所有这些样式对象是什么并绑定它们).
有人能够提供诱惑这个出发点吗?或谷歌一个教程,让我开始?
好吧,我暂时把这件事放在一边了。
但我想我已经想出了一个解决方案。
使用DrawingVisual 和DrawingContext。
这篇博文对我帮助很大:Simple WPF 2D Graphics: DrawingVisual
首先,我们需要获取 Visual 类(请注意,此代码已拼凑在一起,清理是个好主意):
public class MyVisualHost : FrameworkElement
{
private readonly VisualCollection children;
public MyVisualHost(int width)
{
children = new VisualCollection(this);
var visual = new DrawingVisual();
children.Add(visual);
var currentTime = new TimeSpan(0, 0, 0, 0, 0);
const int everyXLine100 = 10;
double currentX = 0;
var currentLine = 0;
double distanceBetweenLines = 5;
TimeSpan timeStep = new TimeSpan(0, 0, 0, 0, 10);
int majorEveryXLine = 100;
var grayBrush = new SolidColorBrush(Color.FromRgb(192, 192, 192));
grayBrush.Freeze();
var grayPen = new Pen(grayBrush, 2);
var whitePen = new Pen(Brushes.White, 2);
grayPen.Freeze();
whitePen.Freeze();
using (var dc = visual.RenderOpen())
{
while (currentX < width)
{
if (((currentLine % majorEveryXLine) == 0) && currentLine != 0)
{
dc.DrawLine(whitePen, new Point(currentX, 30), new Point(currentX, 15));
var text = new FormattedText(
currentTime.ToString(@"hh\:mm\:ss\.fff"),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Tahoma"),
8,
grayBrush);
dc.DrawText(text, new Point((currentX - 22), 0));
}
else if ((((currentLine % everyXLine100) == 0) && currentLine != 0)
&& (currentLine % majorEveryXLine) != 0)
{
dc.DrawLine(grayPen, new Point(currentX, 30), new Point(currentX, 20));
var text = new FormattedText(
string.Format(".{0}", currentTime.Milliseconds),
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
new Typeface("Tahoma"),
8,
grayBrush);
dc.DrawText(text, new Point((currentX - 8), 8));
}
else
{
dc.DrawLine(grayPen, new Point(currentX, 30), new Point(currentX, 25));
}
currentX += distanceBetweenLines;
currentLine++;
currentTime += timeStep;
}
}
}
// Provide a required override for the VisualChildrenCount property.
protected override int VisualChildrenCount { get { return children.Count; } }
// Provide a required override for the GetVisualChild method.
protected override Visual GetVisualChild(int index)
{
if (index < 0 || index >= children.Count)
{
throw new ArgumentOutOfRangeException();
}
return children[index];
}
}
Run Code Online (Sandbox Code Playgroud)
接下来我们需要绑定:
public static readonly DependencyProperty HeaderDrawingVisualProperty = DependencyProperty.Register("HeaderDrawingVisual", typeof(MyVisualHost), typeof(MainWindow));
public MyVisualHost VisualHost
{
get { return (MyVisualHost)GetValue(HeaderDrawingVisualProperty); }
set { SetValue(HeaderDrawingVisualProperty, value); }
}
Run Code Online (Sandbox Code Playgroud)
XAML:
<Canvas x:Name="Header" Background="#FF2D2D30" Grid.Row="0">
<ContentPresenter Content="{Binding HeaderDrawingVisual}" />
</Canvas>
Run Code Online (Sandbox Code Playgroud)
然后只需在代码中设置:
Header.Width = 50000;
VisualHost = new MyVisualHost(50000);
Run Code Online (Sandbox Code Playgroud)
我的测试表明,使用这种新方法使用 50000 的宽度,我看到了很大的增长!
Old way Total Milliseconds: 277.061
New way Total Milliseconds: 13.9982
Old way Total Milliseconds: 518.4632
New way Total Milliseconds: 12.9423
Old way Total Milliseconds: 479.1846
New way Total Milliseconds: 23.4987
Old way Total Milliseconds: 477.1366
New way Total Milliseconds: 12.6469
Old way Total Milliseconds: 481.3118
New way Total Milliseconds: 12.9678
Run Code Online (Sandbox Code Playgroud)
第一次的时间较少,因为重建时必须清除物品。
| 归档时间: |
|
| 查看次数: |
530 次 |
| 最近记录: |