WPF绘图如何在不拉伸笔画的情况下进行拉伸

6

我需要在边框控件(或类似控件)内绘制一些简单的直线,这些直线始终延伸到边框的边界。有没有办法只拉伸线而不拉伸其笔?不需要涉及太多C#代码吗?

在这个版本中,这些直线会被拉伸:

<Border>
   <Border.Background>
      <DrawingBrush>
         <DrawingBrush.Drawing>
            <DrawingGroup>
               <GeometryDrawing Brush="Red">
                  <GeometryDrawing.Geometry>
                     <GeometryGroup>
                        <RectangleGeometry Rect="0,0 100,1000" />
                        <LineGeometry  StartPoint="0,0" EndPoint="100,1000"/>
                        <LineGeometry  StartPoint="100,0" EndPoint="0,1000"/>
                     </GeometryGroup>
                  </GeometryDrawing.Geometry>
                  <GeometryDrawing.Pen>
                     <Pen Thickness="20" Brush="Black"/>
                  </GeometryDrawing.Pen>
               </GeometryDrawing>
            </DrawingGroup>
         </DrawingBrush.Drawing>
      </DrawingBrush>
   </Border.Background>
</Border>

我想到的最好解决方案是这样的:
<Border>
   <Grid>
      <Path Stretch="Fill" Fill="Red" Stroke="Black" StrokeThickness="4"  Data="M0,0 L100,0 100,1000 0,1000 z" />
      <Path Stretch="Fill" Stroke="Black" StrokeThickness="4"  Data="M 0,0 L0,0 100,1000" />
      <Path Stretch="Fill" Stroke="Black" StrokeThickness="4"  Data="M 100,0 L100,0 0,1000" />
   </Grid>
</Border>

但是难道没有更好的解决方案吗?不需要额外使用 Grid 布局吗?

3个回答

5

我是通过调整路径数据而不是视觉组件来完成这个操作的。

  1. 将路径放置在画布中。
  2. 将路径数据设置为表示逻辑范围百分比的几何图形。
  3. 将路径数据变换设置为一个ScaleTransform,其中ScaleX和ScaleY绑定到实际宽度和高度。

1
真是个好技巧!省了我好几个小时的挣扎或者大量的转换工作。 - Julien Lebosquain

4

在一条线内,你可以将宽度(或高度,取决于你画线的方向)与父容器绑定,以实现你想要的效果。

    <Grid x:Name="Grid" Margin="10">
        <Border BorderBrush="Black" BorderThickness="1"  />
        <Line X1="0" X2="{Binding ElementName=Grid, Path=ActualWidth}" Y1="1" Y2="1" Stroke="Red" Margin="0,10,0,0" />
        <Line X1="0" X2="{Binding ElementName=Grid, Path=ActualWidth}" Y1="1" Y2="1" Stroke="Green" Margin="0,30,0,0" />
        <Line X1="0" X2="{Binding ElementName=Grid, Path=ActualWidth}" Y1="1" Y2="1" Stroke="Blue" Margin="0,50,0,0" />
    </Grid>

编辑:以下是不使用绑定的另一种方法

<Border BorderBrush="Black" BorderThickness="1" >
    <Path Stroke="Red" StrokeThickness="1" Data="M0,0 1,0Z" Stretch="Fill" />
</Border>

你在VS 2008中尝试过这个吗(我认为Blend也可以)?设计师将无限缩放此类控件。它变得越来越大。这是因为绑定到父级实际宽度的线条实际上比实际宽度略长(考虑LineCap等)。这将导致实际宽度增加,从而导致线条端点被更新,依此类推。 - bitbonk
在我的VS2008设计器中看起来很好。运行时也很正常。 - mdm20
只有在省略网格并直接放入用户控件中时才会出现这种情况。 - bitbonk
很好的观点mdm20 - 您可以使用Line元素进行简单操作。但是,一旦您需要除(0,0)和(ActualWidth,ActualHeight)之外的坐标,您的代码就会陷入转换器和MultiBindings的混乱中。更不用说它在运行时效率更低了。 - Kent Boogaart

1

我不知道有没有现成的解决方案。但是,除非你正在做一些非常奢侈的事情,否则覆盖OnRender并自己绘制并不需要太多的工作:

public class CustomBorder : Border
{
    protected override void OnRender(DrawingContext dc)
    {
        base.OnRender(dc);

        dc.DrawLine(new Pen(BorderBrush, BorderThickness.Top), new Point(0, 0), new Point(ActualWidth, ActualHeight));
    }
}

结果:

enter image description here


1
我很惊讶我必须自己编写控件来完成这么简单的事情。 - bitbonk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接