Getting strings that look sharp in WPF can be quite complicated! And a few times ... it seems like a little black magic is needed!
I think the answers to the paired and kimki are pointing in the right direction. That is, often you want to place single pixel lines on a border of 0.5 pixels ... given the way it draws a line (half on one side and half on the other).
However, this is not always so simple. For example, it also depends on the surrounding xaml . For example, try executing this code and resize it:
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center"> <Line X1="0" Y1="5" X2="200" Y2="5" StrokeThickness="1" Stroke="Black" UseLayoutRounding="True"/> <Line X1="0" Y1="15" X2="200" Y2="15" StrokeThickness="1" Stroke="Black" UseLayoutRounding="True"/> </Canvas>
Then try this code (again, resize when you do this):
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center" UseLayoutRounding="True"> <Line X1="0" Y1="5" X2="200" Y2="5" StrokeThickness="1" Stroke="Black"/> <Line X1="0" Y1="15" X2="200" Y2="15" StrokeThickness="1" Stroke="Black"/> </Canvas>
The only difference between the two fragments is that the first uses UseLayoutRounding on the lines, and the second uses UseLayoutRounding in the Canvas container (which then also inherits the properties of the lines).
However, this difference gives some interesting results. When UseLayoutRounding is used on a container, single pixel lines constantly remain scattered over 2 pixels and they do not move. When UseLayoutRounding is used directly on the lines, and you resize, the lines will sometimes have 1 pixel of sharpness ... and other times will be speada by 2 pixels.
And that leads me to the xaml pattern in the original question. A few comments about this:
- First, you must understand that the UseLayoutRounding and SnapsToDevicePixels properties are inherited. That is, if you use it in the layout container, it inherits the elements in the layout container.
- UseLayoutRounding and SnapsToDevicePixels do not have to be used together. They may be ... but I usually try to use them separately ... either one or the other. More info here: When should I use SnapsToDevicePixels in WPF 4.0?
- The TextOptions.TextFormattingMode parameters affect the text, not the lines.
- This StackPanel, which you use as the layout container, can also affect how the lines are drawn. Canvas allows you to more accurately control the positioning of your lines. A StackPanel will simply place one line after another line ... and may produce unexpected results.
More information than the original poster would have liked. However, I personally know how difficult it is to use lines in WPF. Hope this info helps someone!