10000's+ UI elements, bind or draw?
- by jpiccolo
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?