Jef Patat
Jef Patat

Reputation: 999

WPF blurry adorner

I'm implementing some drag/drop functionality on a treeview.

I'm trying to draw an insertion point marker, but it's coming out blurry:

enter image description here

How can I make it render crisply and sharp?

This is my template:

<HierarchicalDataTemplate DataType="{x:Type localvm:TreeViewItemViewModel}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}">
    <i:Interaction.Behaviors>
        <b:TreeViewItemDragBehavior/>
        <b:TreeViewItemDropBehavior/>
    </i:Interaction.Behaviors>
</TextBlock>

This is my render logic:

protected override void OnRender(DrawingContext drawingContext)
{
    Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);

    SolidColorBrush renderBrush = new SolidColorBrush(Colors.Blue);
    renderBrush.Opacity = 0.5;
    Pen renderPen = new Pen(new SolidColorBrush(Colors.Blue), 1.5);

    if (IsInUpperHalf)
    {
        drawingContext.DrawLine(renderPen, adornedElementRect.TopLeft, adornedElementRect.TopRight);

        Point point1 = new Point(adornedElementRect.TopLeft.X + 10, adornedElementRect.TopLeft.Y);
        Point point2 = new Point(adornedElementRect.TopLeft.X, adornedElementRect.TopLeft.Y + 3);
        StreamGeometry leftStreamGeometry = new StreamGeometry();
        using (StreamGeometryContext geometryContext = leftStreamGeometry.Open())
        {
            geometryContext.BeginFigure(adornedElementRect.TopLeft, true, true);
            PointCollection points = new PointCollection { point1, point2 };
            geometryContext.PolyLineTo(points, true, true);
            drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Blue, 1), leftStreamGeometry);
        }
        StreamGeometry rightStreamGeometry = new StreamGeometry();
        using (StreamGeometryContext geometryContext = rightStreamGeometry.Open())
        {
            geometryContext.BeginFigure(adornedElementRect.TopRight, true, true);
            PointCollection points = new PointCollection { point3, point4 };
            geometryContext.PolyLineTo(points, true, true);
            drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Blue, 1), rightStreamGeometry);
        }
    }
}

I've been playing with UseLayoutRounding and SnapToDevicePixels in the adorner constructor but it seems I'm missing something.

Upvotes: 1

Views: 395

Answers (1)

Jef Patat
Jef Patat

Reputation: 999

With the guidance of Brian and some tinkering this seems to fix the issue. The main problem I kept having after Brian's comment was that the guidlines needed half a pen width extra for them to work. I only found this out by searching for examples, but no hint on MSDN. Here is my functioning code:

    protected override void OnRender(DrawingContext drawingContext)
    {
        Rect adornedElementRect = new Rect(this.AdornedElement.DesiredSize);
        Pen renderPen = new Pen(new SolidColorBrush(Colors.Blue), 1);
        double halfPenWidth = renderPen.Thickness / 2;

        GuidelineSet guidelines = new GuidelineSet();
        guidelines.GuidelinesX.Add(adornedElementRect.TopLeft.X + halfPenWidth);
        guidelines.GuidelinesX.Add(adornedElementRect.BottomRight.X + halfPenWidth);
        guidelines.GuidelinesY.Add(adornedElementRect.TopLeft.Y + halfPenWidth);
        guidelines.GuidelinesY.Add(adornedElementRect.BottomRight.Y + halfPenWidth);
        drawingContext.PushGuidelineSet(guidelines);


        if (IsInUpperHalf)
        {
            drawingContext.DrawLine(renderPen, adornedElementRect.TopLeft, adornedElementRect.TopRight);
            StreamGeometry leftStreamGeometry = new StreamGeometry();
            using (StreamGeometryContext geometryContext = leftStreamGeometry.Open())
            {
                geometryContext.BeginFigure(adornedElementRect.TopLeft, true, true);
                geometryContext.LineTo(new Point(adornedElementRect.TopLeft.X + 10, adornedElementRect.TopLeft.Y), false, false);
                geometryContext.LineTo(new Point(adornedElementRect.TopLeft.X, adornedElementRect.TopLeft.Y + 3), false, false);
                drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Blue, 1), leftStreamGeometry);
            }
            StreamGeometry rigthStreamGeometry = new StreamGeometry();
            using (StreamGeometryContext geometryContext = rigthStreamGeometry.Open())
            {
                geometryContext.BeginFigure(adornedElementRect.TopRight, true, true);
                geometryContext.LineTo(new Point(adornedElementRect.TopRight.X, adornedElementRect.TopRight.Y + 3), false, false);
                geometryContext.LineTo(new Point(adornedElementRect.TopRight.X - 10, adornedElementRect.TopRight.Y), false, false);
                drawingContext.DrawGeometry(Brushes.Blue, new Pen(Brushes.Blue, 1), rigthStreamGeometry);
            }
        }
    }

Upvotes: 1

Related Questions