如何在wpf中绘制带方角的边框?

时间:2010-09-09 16:13:08

标签: wpf graphics line border

你知道,就像太空堡垒纸一样!我已经给了这几个但是现在我很难过。我还没有走下几何路线,所以我会尽可能地解释这个。

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

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

我已经做了两次尝试:

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

    <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>
    

    “线”设置为缩放为网格大小。将“行”属性设置为X1="0" X2="1" Y1="1" Y2="0"并使用Stretch="Fill"将“线”展开到边缘。但是,它最终看起来像这样:

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

    我在托管Line的Grid元素周围绘制了洋红色边框,以使问题更加明显。

    如何将线扩展到真正填补空白(例如通过在网格内膨胀可绘制区域),或者有更好的方法吗? < / p>

    此外,转换会扭曲线条,使其更厚。我尝试扩大规模,但没有一致性。线上的端盖看起来一样糟糕(例如Triangle)。

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

    感谢阅读,汤姆

2 个答案:

答案 0 :(得分:4)

WPF边框继承自Decorator类。编写自己的Decorator非常容易。下面是一个围绕着一个“藏在角落里”的孩子的边界。

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>

答案 1 :(得分:0)

为了避免最后的讨厌的休息,你可以使用Polygon或PolyLine:

    <Polygon
        Stroke="Red"
        StrokeThickness="2"
        Points="
            0,1 1,0
            1,0 20,0
            20,0 21,1
            21,1 21,20
            21,20 20,21
            20,21 1,21
            1,21 0,20
            0,1 1,0
        "
        Stretch="Fill"
        />

我选择的宽度是任意的......