如何在wpf中绘制带有方角的边框? [英] How can I draw a border with squared corners in wpf?

查看:32
本文介绍了如何在wpf中绘制带有方角的边框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你知道,就像太空堡垒纸!我已经尝试了几次,但现在我很难过.我还没有沿着几何路线走下去,所以我会尽可能地解释这一点.

You know, like Battlestar paper! I have given this a few goes but now I'm stumped. I haven't yet gone down the geometery route, so I'll explain this as best as I can.

我希望边框足够大,但包含固定大小的角,就像 CornerRadius 一样.我希望它们是锥形的,而不是圆角,例如:

I'd like the border to be sizable, but contain fixed-size corners, just like CornerRadius does. Instead of rounded corners, I'd like them to be tapered, like:

/---------
|         |
|         |
\_________/

我为此做了两次尝试:

  1. 我第一次尝试操作边界类.这不起作用,因为拉伸形状会破坏几何形状和比例.
  2. 第二次尝试更加开箱即用.字面上地.我创建了一个 3x3 网格并用 4 个边框填充它,每个边框的厚度分别为 2,0,0,0 - 0,2,0,0 - 0,0,2,0 和 0,0,0,2.最后一步,是用一条线连接边界.我的问题就在这里......

第一次尝试

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Grid>
      <Grid.Resources>
         <Style x:Key="MyPoly" TargetType="Polygon">
            <Setter Property="Points">
               <Setter.Value>
                  <PointCollection>
                     <Point X="0.10" Y="0.01"/>
                     <Point X="0.50" Y="0.01"/>
                     <Point X="0.60" Y="0.10"/>
                     <Point X="0.60" Y="0.50"/>
                     <Point X="0.50" Y="0.60"/>
                     <Point X="0.10" Y="0.60"/>
                     <Point X="0.01" Y="0.50"/>
                     <Point X="0.01" Y="0.10"/>
                  </PointCollection>
               </Setter.Value>
            </Setter>
         </Style>
      </Grid.Resources>
      <Border
         Width="100"
         Height="100"
         BorderBrush="Black"
         BorderThickness="3"
         CornerRadius="5"/>
      <Grid Width="400"
            Height="300">
         <Polygon
            Stroke="Purple"
            StrokeThickness="2"
            Style="{StaticResource MyPoly}" Stretch="Fill">
            <Polygon.Fill>
               <SolidColorBrush Color="Blue" Opacity="0.4"/>
            </Polygon.Fill>
            <Polygon.LayoutTransform>
               <ScaleTransform ScaleX="1" ScaleY="1"/>
            </Polygon.LayoutTransform>
         </Polygon>
      </Grid>
   </Grid>
</Page>

第二次尝试

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" SnapsToDevicePixels="True">
    <Grid>
        <Grid.Resources>
        </Grid.Resources>
        <Grid Width="200" Height="350" SnapsToDevicePixels="True">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="10"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="10"/>
                <RowDefinition Height="*"/>
                <RowDefinition Height="10"/>
            </Grid.RowDefinitions>
            <Border Grid.Column="0" Grid.Row="1" Margin="0" BorderBrush="Red" BorderThickness="2,0,0,0" Padding="0" SnapsToDevicePixels="True"/>
            <Border BorderThickness="1" BorderBrush="Black">
                <Line SnapsToDevicePixels="True" Stretch="Fill" Stroke="Red" StrokeThickness="2" X1="0" X2="1" Y1="1" Y2="0">
                </Line>
            </Border>
            <Border Grid.Column="1" Grid.Row="0" BorderBrush="Red" BorderThickness="0,2,0,0" SnapsToDevicePixels="True"/>
            <Border Grid.Column="2" Grid.Row="1" BorderBrush="Red" BorderThickness="0,0,2,0" SnapsToDevicePixels="True"/>
            <Border Grid.Column="1" Grid.Row="2" BorderBrush="Red" BorderThickness="0,0,0,2" SnapsToDevicePixels="True"/>
        </Grid>
    </Grid>
</Page>

线条设置为缩放到网格大小.将 Line 属性设置为 X1="0" X2="1" Y1="1" Y2="0" 并使用 Stretch="Fill" 将 Line 扩展为边缘.然而,它最终看起来像这样:

The Line is set to scale to the grid size. Setting the Line properties to X1="0" X2="1" Y1="1" Y2="0" and using Stretch="Fill" expands the Line to the edges. However, it ends up looking like this:

(烦人的是,我不能发布图片,我需要回答别人的问题才能获得一些代表.所以请转至此链接查看该行,或将上述 XAML 粘贴到 Kaxaml 中.)http://img375.imageshack.us/img375/1996/border1.png

(Annoyingly, I can't post images, I need to go answer someone elses questions to earn some rep. So instead please go to this link to see the line, or paste the above XAML into Kaxaml.) http://img375.imageshack.us/img375/1996/border1.png

我在包含 Line 的 Grid 元素周围画了一个洋红色边框,以使问题更加明显.

I drew a magenta border around the Grid element hosting the Line, to make the problem more obvious.

如何扩展线条以真正填补空白(例如,通过扩大网格内的可绘制区域),或者有更好的方法吗?

How can I expand the line to really fill the gap (for example by inflating the drawable area within the grid), or, is there a better way?

此外,变换会扭曲线条,使其变粗.我尝试扩大规模,但没有一致性.线上的端点看起来同样糟糕(例如三角形).

Also, transformations distort the line, making it thicker. I tried scaling up but there wasn't a consistency to this. Endcaps on the line look just as bad (Triangle for example).

最后,这个方法还是有缺陷的,因为我希望以后能够设置角的大小,所以将行/列的边宽设置为10似乎是一个绊脚石.绑定到属性可能会解决这个问题,但我从未在 Style 中这样做过.

Finally, this method is still flawed, because I want to be able to set the corner size in the future, so having the edge width for the row/column set to 10 seems like a stumbling point. Binding to a property might solve that, I've never done that in a Style though.

感谢阅读,汤姆

推荐答案

WPF 边框继承自类装饰器.编写自己的装饰器非常容易.下面的一个在一个孩子周围画了一个边界,里面有隐藏"的角落.

The WPF border is inheriting from class Decorator. It is pretty easy to write your own Decorator. Below one draws a border around a child with "tucked in" corners.

class FunkyBorder : Decorator
{
    public Brush BorderBrush
    {
        get { return (Brush)GetValue(BorderBrushProperty); }
        set { SetValue(BorderBrushProperty, value); }
    }

    public static readonly DependencyProperty BorderBrushProperty =
        DependencyProperty.Register("BorderBrush", 
                                    typeof(Brush), 
                                    typeof(FunkyBorder), 
                                    new UIPropertyMetadata(Brushes.Transparent));

    protected override void OnRender(DrawingContext drawingContext)
    {
        // TODO, make pen thickness and corner width (currently 10) into dependency properties.
        // Also, handle case when border don't fit into given space without overlapping.

        if (_pen.Brush != BorderBrush)
        {
            _pen.Brush = BorderBrush;
        }

        drawingContext.DrawLine(_pen, new Point(0, 10), new Point(10, 0));
        drawingContext.DrawLine(_pen, new Point(10, 0), new Point(ActualWidth - 10, 0));
        drawingContext.DrawLine(_pen, new Point(ActualWidth - 10, 0), new Point(ActualWidth, 10));
        drawingContext.DrawLine(_pen, new Point(0, 10), new Point(0, ActualHeight - 10));
        drawingContext.DrawLine(_pen, new Point(ActualWidth, 10), new Point(ActualWidth, ActualHeight - 10));
        drawingContext.DrawLine(_pen, new Point(0, ActualHeight - 10), new Point(10, ActualHeight));
        drawingContext.DrawLine(_pen, new Point(10, ActualHeight), new Point(ActualWidth - 10, ActualHeight));
        drawingContext.DrawLine(_pen, new Point(ActualWidth - 10, ActualHeight), new Point(ActualWidth, ActualHeight - 10));
    }

    private Pen _pen = new Pen(Brushes.Transparent, 2);
}

像这样使用:

   <BorderTest:FunkyBorder BorderBrush="Red">
        <TextBlock Text="Hello" />
    </BorderTest:FunkyBorder>

这篇关于如何在wpf中绘制带有方角的边框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆