Question

I have a WPF canvas that I can scale, scroll and whatever. Now I want to draw (tiling) gridlines on it - preferably depending on the scale, which means that when you zoom out the old gridlines fade away and new (bigger scale, but due to zooming seemingly the same) gridlines fade in.

I've heard some people yelling "Tilebrush!", but I can't google any example of it.

Can anybody point me in the right direction - not just to the MSDN page of the tilebrush, but on how to efficiently draw gridlines on my zoomable canvas ? :)

Was it helpful?

Solution

The easiest solution is to use a VisualBrush to draw your gridlines:

<Canvas>
  <Canvas.Background>
    <VisualBrush TileMode="Tile" Stretch="Fill" Viewport="0 0 50 50" ViewportUnits="Absolute" ViewboxUnits="Absolute" >
      <VisualBrush.Visual>
        <Grid>
          <Rectangle Width="1" Height="0.03" Fill="Gray" HorizontalAlignment="Left" VerticalAlignment="Top" />
          <Rectangle Height="1" Width="0.03" Fill="Gray" HorizontalAlignment="Left" VerticalAlignment="Top" />
        </Grid>
      </VisualBrush.Visual>
    </VisualBrush>
  </Canvas.Background>
</Canvas>

You can change the gridlines by adjusting the Viewport coordinates and the gridline width by adjusting the rectangle Height and Width (currrently 0.03).

A more efficient solution is available using a DrawingBrush, but working with drawings is not as simple. This draws gridlines using a DrawingBrush:

<Canvas>
  <Canvas.Background>
    <DrawingBrush TileMode="Tile" Stretch="Fill" Viewport="0 0 50 50" ViewportUnits="Absolute" ViewboxUnits="Absolute" >
      <DrawingBrush.Drawing>
        <GeometryDrawing Geometry="M0,0 L0,1 0.03,1 0.03,0.03 1,0.03 1,0 Z" Brush="Gray" />
      </DrawingBrush.Drawing>
    </DrawingBrush>
  </Canvas.Background>
</Canvas>

To change the gridlines as you zoom out, just recompute them whenever the zoom changes. You can determine just how zoomed-in a given visual is with this code:

var zoom = visual
             .TransformToAncestor(Window.FromVisual(visual))
             .Transform(new Point(1,1));

if(zoom.X>10 || zoom.Y>10)
  // Use finer gridlines
else
  // Use coarser gridlines

If you really want to "fade in" the gridlines, you can use two Canvasas under your main Canvas, and set the opacity on the finer gridlines as a function of the exact zoom in use.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top