Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8946085
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T12:25:16+00:00 2026-06-15T12:25:16+00:00

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

  • 0

I am drawing a header for a timeline control.
It looks like this:
enter image description here

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?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T12:25:17+00:00Added an answer on June 15, 2026 at 12:25 pm

    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):

    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];
    }
    }
    

    Next we need our binding:

    public static readonly DependencyProperty HeaderDrawingVisualProperty = DependencyProperty.Register("HeaderDrawingVisual", typeof(MyVisualHost), typeof(MainWindow));
    
    public MyVisualHost VisualHost
    {
        get { return (MyVisualHost)GetValue(HeaderDrawingVisualProperty); }
        set { SetValue(HeaderDrawingVisualProperty, value); }
    }
    

    XAML:

    <Canvas x:Name="Header" Background="#FF2D2D30" Grid.Row="0">
        <ContentPresenter Content="{Binding HeaderDrawingVisual}" />
    </Canvas>
    

    Then just set in code:

    Header.Width = 50000;
    VisualHost = new MyVisualHost(50000);
    

    My testing showed, using a width of 50000 with this new method, I saw a great increase!

    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
    

    Time is less the first time because items have to be cleared when rebuild.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Hello everybody I am drawing dynamic table and I want to add header for
Drawing a blank on this, and google was not helpful. Want to make a
This drawing shows a tree of parent-child relationships. It is directed, without cycles. A
I'm drawing a 3d scene in 5-6 drawcalls, but I have about 60000-65000 triangles
I've already got my custom header drawing in my GridView using SetRenderMethodDelegate on the
I'm drawing out a listing of menu items inside a wordpress template (header.php) and
I have been experiencing strange behavior with the header drawing the first time. Here
I would like to add a header and footer image to a h:message in
I cannot get this style to work. Take a look at my drawing: Markup:
So far I have this code. $form = New-Object System.Windows.Forms.Form $form.Size = New-Object System.Drawing.Size(900,600)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.