tags:

views:

839

answers:

4

Hope anyone can shed light on this so I can use pens with dash patterns?

I am writing a scrollable chart (a Panel inside ScrollViewer that implements IScrollInfo) in WPF using DrawingVisual's DataContext.DrawX. I have several thousand DrawingVisuals that get scrolled by using TranslateTransform on the Panel that hosts them. I implemented a grid by placing a Panel on top of it and drawing simple horizontal lines from one edge to the other using DataContext.DrawLine(pen, new Point(0, y), new Point(widthOfPanel, y)); //(note: these lines are always static, they never move).

The scroll performance is absolutely insane (i.e. DrawingVisual's are drawn instantly and scrolling is instant). But if I use a Pen that uses dash patterns (see below for example) to draw the grid lines, then scrolling is very jerky and the performance seems to have been decreased by a factor of 100 (an estimate). Can anyone explain why that happens and how I can workaround this?

Example of Pen with dash pattern:

<Pen x:Key="PenUsingDashPatterns" Brush="Black" Thickness="1">
   <Pen.DashStyle >
      <DashStyle Dashes="3, 3" />
   </Pen.DashStyle>
</Pen>
+3  A: 

Are the pens getting frozen? Freezing drawing objects helps performance a lot.

You could set up a Loaded handler and debug to see if your pens are frozen. If not, Call the Pen.Freeze() button manually on them.

Note that freeze also makes the pens read-only... you will be unable to modify them after you freeze them.

Josh G
It's strange how my bounty went to the only answer that was not helpful. I didn't pick it and don't know to change this.
Hermann
Sorry my answer wasn't helpful. After the period for the bounty expires, it will automatically assign as the answer the response with the most votes.
Josh G
+2  A: 

Most likely this is because this particular draw operation isn't something that can be delegated to the video card, which would force composition in memory and blitting to the video card.

Peter Wone
+3  A: 

You should use Perforator to dig deeper into the performance issue. Here's a link to the MSDN site talking about various WPF performance tools. Perforator would probably be the tool that will help you the most, specially in determining if the lines are being drawn using the software renderer (which would be the greatest factor in giving you such bad performance).

If the problem is that they are being drawn in software, you might have to write your own ShaderEffect, but that will probably get tricky fast unless you are familiar with HLSL.

Erich Mirabal
+1 for advising measurements
David Schmitt
Thanks, but I've tried the WPF performance tools. They are pretty much useless when working with Visuals. I've had more luck with traditional performance tools and debugging WPF source code and my conclusion was that it could have been implemented much more efficiently. But I guess that is the trade off for getting all that productivity.
Hermann
+3  A: 

Here's a possible workaround - if you're only drawing horizontal and/or vertical lines you could try creating your Pen with a checker pattern DrawingBrush such as:

  <Pen x:Key="PenUsingDashPatterns" Thickness="1">
        <Pen.Brush>
            <DrawingBrush TileMode="Tile" 
                          Viewport="0 0 6 6" ViewportUnits="Absolute">
                <DrawingBrush.Drawing>
                    <GeometryDrawing Brush="Black">
                        <GeometryDrawing.Geometry>
                            <GeometryGroup>
                                <RectangleGeometry  Rect="0 0 3 3"/>
                                <RectangleGeometry  Rect="3 3 3 3"/>
                            </GeometryGroup>
                        </GeometryDrawing.Geometry>
                    </GeometryDrawing>
                </DrawingBrush.Drawing>
            </DrawingBrush>
        </Pen.Brush>
    </Pen>

Alternatively, you could use different brushes for verical and horizontal lines, or, possibly, an ImageBrush for better performance.

Danko Durbić
Thanks, I tried it, but I did not improve performance.
Hermann