0

I need to create a User Control in WPF with several shapes in a grid. The UserC ontrol should have beveled corners. I have no idea how to do that without drawing triangles at fixed positions.

enter image description here

icebat
  • 4,696
  • 4
  • 22
  • 36
Konstantin
  • 13
  • 3
  • 5
    This question would be much better with a reference image as an example of what you are trying to recreate. – Gusdor Mar 14 '16 at 11:26
  • This should be the result: http://www.directupload.net/file/d/4293/jd6x6z2b_png.htm – Konstantin Mar 14 '16 at 12:43
  • [This similar question](http://stackoverflow.com/questions/561931/how-to-create-trapezoid-tabs-in-wpf-tab-control) should help. – icebat Mar 14 '16 at 13:29

1 Answers1

0

In my opinion you should write your own Decorator. I wrote a simple code sample, which of course can be improved - maybe it should be. You can use my CutCornerBorder class ad an hint:

public class CutCornerBorder : Decorator
{
    private Pen cachedPen;

    public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register("BorderThickness", typeof(double), typeof(CutCornerBorder), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(CutCornerBorder.OnClearPenCache)));

    public static readonly DependencyProperty PaddingProperty = DependencyProperty.Register("Padding", typeof(Thickness), typeof(CutCornerBorder), new FrameworkPropertyMetadata(default(Thickness), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender), new ValidateValueCallback(CutCornerBorder.IsThicknessValid));

    public static readonly DependencyProperty CornerCutProperty = DependencyProperty.Register("CornerCut", typeof(double), typeof(CutCornerBorder), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender), new ValidateValueCallback(CutCornerBorder.IsCornerCutValid));

    public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register("BorderBrush", typeof(Brush), typeof(CutCornerBorder), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender, new PropertyChangedCallback(CutCornerBorder.OnClearPenCache)));

    private static void OnClearPenCache(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        CutCornerBorder cutCornerBorder = (CutCornerBorder)d;
        cutCornerBorder.cachedPen = null;
    }

    private static bool IsCornerCutValid(object value)
    {
        /* You can add here your own validation logic */
        return true;
    }

    private static bool IsThicknessValid(object value)
    {
        Thickness thickness = (Thickness)value;
        /* You can add here your own validation logic */
        return true
    }

    public double BorderThickness
    {
        get
        {
            return (double)base.GetValue(BorderThicknessProperty);
        }
        set
        {
            base.SetValue(BorderThicknessProperty, value);
        }
    }

    public double CornerCut
    {
        get
        {
            return (double)base.GetValue(CornerCutProperty);
        }
        set
        {
            base.SetValue(CornerCutProperty, value);
        }
    }

    public Thickness Padding
    {
        get
        {
            return (Thickness)base.GetValue(PaddingProperty);
        }
        set
        {
            base.SetValue(PaddingProperty, value);
        }
    }

    public Brush BorderBrush
    {
        get
        {
            return (Brush)base.GetValue(BorderBrushProperty);
        }
        set
        {
            base.SetValue(BorderBrushProperty, value);
        }
    }

    protected override void OnRender(DrawingContext dc)
    {
        if (BorderThickness > 0 && BorderBrush != null)
        {
            Pen pen = cachedPen;
            if (pen == null)
            {
                pen = new Pen();
                pen.Brush = BorderBrush;
                pen.Thickness = BorderThickness;

                if (BorderBrush.IsFrozen)
                {
                    pen.Freeze();
                }
                cachedPen = pen;
            }

            if (BorderThickness > 0)
            {
                double num = pen.Thickness * 0.5;
                /* Left */
                dc.DrawLine(pen, new Point(num, CornerCut), new Point(num, RenderSize.Height - CornerCut));
                /* Right */
                dc.DrawLine(pen, new Point(RenderSize.Width - num, CornerCut), 
                    new Point(RenderSize.Width - num, RenderSize.Height - CornerCut));

                /* Top */
                dc.DrawLine(pen, new Point(CornerCut, num), new Point(RenderSize.Width - CornerCut, num));
                /* Bottom */
                dc.DrawLine(pen, new Point(CornerCut, RenderSize.Height - num), new Point(RenderSize.Width - CornerCut, RenderSize.Height - num));

                dc.DrawLine(pen, new Point(num, CornerCut), new Point(CornerCut, num));
                dc.DrawLine(pen, new Point(RenderSize.Width - CornerCut, num), new Point(RenderSize.Width - num, CornerCut));
                dc.DrawLine(pen, new Point(RenderSize.Width - num, RenderSize.Height - CornerCut),
                    new Point(RenderSize.Width - CornerCut, RenderSize.Height - num));
                dc.DrawLine(pen, new Point(CornerCut, RenderSize.Height - num),
                    new Point(num, RenderSize.Height - CornerCut));
            }
        }
    }
}

As you can see OnRender method does the "dirty job" (by drawing the cut border). So in your XAML you can write:

<local:CutCornerBorder BorderBrush="Black" BorderThickness="3" CornerCut="40" Margin="30">
    <TextBlock Text="HELLO!" FontSize="18" HorizontalAlignment="Center" 
                VerticalAlignment="Center" Background="Green" Margin="20" />
</local:CutCornerBorder>

I hope it can help you with your issue.

Il Vic
  • 5,576
  • 4
  • 26
  • 37