I am drawing a header for a timeline control.
It looks like this:

I go to 0.01 millisecond per line, so for a 10 minute timeline I am looking at drawing 60000 lines + 6000 labels.
This takes a while, ~10 seconds.
I would like to offload this from the UI thread.
My code is currently:
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;
}
}
I had looked into BackgroundWorker, except you can’t create UI elements on a non-UI thread.
Is it possible at all to do drawHeaderLines in a non-UI thread?
Could I use data binding for drawing the lines?
Would this help with UI responsiveness?
I would imagine I can use databinding, but the Styling is probably beyond my current WPF ability (coming from winforms and trying to learn what all these style objects are and binding them).
Would anyone be able to supply a starting point for tempting this out? Or Google a tutorial that would get me started?
Well I had put this on the back burner for a little but.
But I think I have come up with a solution.
To use DrawingVisual and DrawingContext.
This blog post helped me quite a bit: Simple WPF 2D Graphics: DrawingVisual
First we need to get our Visual class (note this code has been slapped together, cleaning is a good idea):
Next we need our binding:
XAML:
Then just set in code:
My testing showed, using a width of 50000 with this new method, I saw a great increase!
Time is less the first time because items have to be cleared when rebuild.