views:

332

answers:

1

I'm using the WPF Grid to align objects, and ran into a rather glaring issue regarding pixel alignment of columns. I tried to remove as many variables as possible, and managed to show the issue in this code:

<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100.5" />
        <ColumnDefinition Width="199.5" />
    </Grid.ColumnDefinitions>
    <Border Background="Red">
        <Grid.Column>1</Grid.Column>
    </Border>
    <Border Background="Red">
    </Border>
</Grid>
</Window>

If you run that sample, it's easy to see that there's an issue in the border between the two columns. It's caused, I believe, because WPF simply alpha-blends one column with the background and the other with the result, even though conceptually both columns are in the same Z, so the pixel should be the blending of the sum of their weights and the background.

I understand this is a problematic issue, and naturally I don't intentionally create columns with partial pixel sizes, but the same effect can be easily observed when using star sizes (which I do use a lot).

This issue can be worked around by using the SnapsToDevicePixels property ( instead of ). this works because WPF has internally-consistent rounding, so both columns snap to the same pixel. However, I hit a related problem which is very similar in vein, to which I couldn't find a solution.

For some reason, when using the Geometry class, I get the same sort of pixel alignment issues, and I this time I didn't find any sort of work-around. It's as if the pixels are rounded, but now the Geometry is snapped one pixel off, leaving a hole 1-pixel-wide hole.

Example code:

<Window x:Class="Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid SnapsToDevicePixels="False">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100.5" />
        <ColumnDefinition Width="199.5" />
    </Grid.ColumnDefinitions>
    <Border Background="Red">
        <Grid.Column>1</Grid.Column>
    </Border>
    <Border>
        <Border.Background>
            <DrawingBrush>
                <DrawingBrush.Drawing>
                    <GeometryDrawing Brush="Red">
                        <GeometryDrawing.Geometry>
                            <RectangleGeometry Rect="0,0,1,1"></RectangleGeometry>
                        </GeometryDrawing.Geometry>
                    </GeometryDrawing>
                </DrawingBrush.Drawing>
            </DrawingBrush>
        </Border.Background>
    </Border>
</Grid>
</Window>

Any idea how to get my pixels aligned properly?

EDIT:

Working correctly now after adding a GuidelineSet according to the answer. Working drawing code is:

A: 

I believe you must use a GuidelineSet in the case of a Drawing. There's a good section on how to apply GuidelineSets available here in the SDK.

Drew Marsh
Thanks! It worked perfectly - Edited my question with the working code. Seems strange that drawings don't care about their container's SnapsToDevicePixels, though, or at least that DrawingGroup doesn't have its own SnapsToDevicePixels property. I ended up doing exactly what that property does manually...
Roee Shenberg