Friday, March 7, 2008

WPF TileBrush Nonsense

For the absolute life of me I cannot get a custom TileBrush to tile outside of VS2k8 or Blend 2.5. The basics are that I'm constructing a ruler, which started programmatically after finding the current DPI. When that didn't work, I attempted to do the same thing in straight XAML, which wouldn't be relative to the DPI (thus would only be a nice ruler at 96dpi). Even this would not work. At this point my frustration knows no bounds.

The above is a screengrab from inside VS2k8. The screengrab from Blend 2.5 also shows the ruler tiling. Below is a screengrab during runtime, notice the distinctive lack of tiling, and now it is somehow stretching to Fill.

The tiled brush is a DrawingBrush consisting of a GeometryDrawing with a GeometryGroup of LineGeometry's. The annotated XAML is given below:
<DrawingBrush x:Key="RulerBrush"
Stretch="None"
TileMode="Tile"
Viewport="0,0,96,16"
ViewportUnits="Absolute"
Viewbox="0 0 1 1"
ViewboxUnits="RelativeToBoundingBox">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<LineGeometry EndPoint="0,16"
StartPoint="0,0" />
<!-- ... -->
<LineGeometry EndPoint="48,16"
StartPoint="48,4" />
<!-- ... -->
<LineGeometry EndPoint="96,16"
StartPoint="96,0" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Brush="#FF000000"
Thickness="1" />
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>

And the requisite XAML for the display area:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Test.Window1"
x:Name="Window"
Title="Window"
Width="640"
Height="480">
<DockPanel x:Name="LayoutRoot" LastChildFill="True">
<ToolBarTray x:Name="ToolBarTray"
DockPanel.Dock="Top">
<ToolBar x:Name="MenuToolBar"
ToolBar.Band="0"
Width="{Binding Path=ActualWidth, ElementName=ToolBarTray}" />
</ToolBarTray>
<Rectangle x:Name="RulerY"
DockPanel.Dock="Left"
Height="15" Margin="0,15,0,0"
Fill="{DynamicResource RulerBrush}">
<Rectangle.LayoutTransform>
<RotateTransform Angle="-90.0" />
</Rectangle.LayoutTransform>
</Rectangle>
<Rectangle x:Name="RulerX"
DockPanel.Dock="Top"
Height="15" Margin="0,0,0,0"
Fill="{DynamicResource RulerBrush}"/>
<ScrollViewer Style="{DynamicResource SimpleScrollViewer}"/>
</DockPanel>
</Window>

This is fairly obnoxious!

1 comment:

RG said...

Good info on a starting point for a ruler. Any ideas on how to get an incrementing number on the big tick marks? I've been thinking about it but can't think of an easy way without resorting to writing some code to create the numbers manually.