如何使自定义形状类在构造函数中可见

本文关键字:构造函数 何使 自定义 | 更新日期: 2023-09-27 18:26:39

我正在尝试创建一个自定义形状类,它基本上是一个六边形,但很少有额外的属性和方法。

我尝试从Polygon类继承它,但它不允许,因为Polygon类是密封的,所以我从抽象Shape类继承了它,但不知道下一步该怎么办。到目前为止,我的代码看起来像这个

public class Cell : Shape
{
    private Polygon poly;
    private Point[] points = new Point[6];
    public PointCollection Points { get; set; }
    public double Radius { get; set; }
    public Point Center { get; set; }
    public Cell()
    {
        points[0] = new Point(Center.X - 1 / 2 * Radius, Center.Y - Radius * 0.866);
        points[1] = new Point(Center.X + 1 / 2 * Radius, Center.Y - Radius * 0.866);
        points[2] = new Point(Center.X + Radius, Center.Y);
        points[3] = new Point(Center.X + 1 / 2 * Radius, Center.Y + Radius * 0.866);
        points[4] = new Point(Center.X - 1 / 2 * Radius, Center.Y + Radius * 0.866);
        points[5] = new Point(Center.X - Radius, Center.Y);
        Points = new PointCollection();
        foreach (Point p in points)
            Points.Add(p);
        poly = new Polygon();
        poly.Points = this.Points;
    }
}

现在,我希望能够在XAML中这样声明它:

<local:Cell Center="20,20" Radius="10" Stroke="Blue" Fill="White"/>

我还希望它在构造函数中可见。

我还需要在课堂上添加什么才能做到这一点?是否有我需要实现的某个接口或我需要覆盖的方法?

如何使自定义形状类在构造函数中可见

我做了类似的事情来制作半圆形状。您需要从Shape继承并覆盖DefiningGeometry和MeasureOverride。在"定义几何图形"中,您将进行实际绘制并返回几何图形。

要使属性在XAML中可见,只需将属性添加到类中即可。纯.NET属性将显示,但您可能需要添加依赖项属性并设置AffectsSender FrameworkPropertyMetadataOptions,以便在更改属性时强制重绘。

我的课是这样的:

public class SemiCircle : Shape
{
    /// <summary>
    /// Gets or set the alignment of the semicircle. I.e. where should the flat part point.
    /// </summary>
    public SemiCircleAlignment Alignment
    {
        get { return (SemiCircleAlignment)GetValue(AlignmentProperty); }
        set { SetValue(AlignmentProperty, value); }
    }
    // Using a DependencyProperty as the backing store for alignment.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AlignmentProperty =
        DependencyProperty.Register("Alignment", typeof(SemiCircleAlignment), typeof(SemiCircle), 
        new FrameworkPropertyMetadata(SemiCircleAlignment.Top,FrameworkPropertyMetadataOptions.AffectsRender));
    protected override System.Windows.Media.Geometry DefiningGeometry
    {
        get 
        {
            StreamGeometry geometry = new StreamGeometry();
            using (StreamGeometryContext context = geometry.Open())
            {
                DrawSemiCircle(context);
            }
            geometry.Freeze();
            return geometry;
        }
    }
    protected override Size MeasureOverride(Size constraint)
    {
        if (constraint.Height == double.PositiveInfinity || constraint.Width == double.PositiveInfinity)
        {
            if (double.IsNaN(Width) || double.IsNaN(Height))
            {
                return new Size(0, 0);
            }
            return new Size(Width, Height);
        }
        return constraint;
    }
    private void DrawSemiCircle(StreamGeometryContext context)
    {
        double tOff = StrokeThickness / 2.0;                // an offset to account for stroke thickness
        Point startPt = new Point(tOff, tOff);                                   // upper left corner
        if (Alignment == SemiCircleAlignment.Bottom || Alignment == SemiCircleAlignment.Right)
        {
            startPt = new Point(ActualWidth - tOff, ActualHeight - tOff);        // or lower right corner
        }
        Point endPt = new Point(ActualWidth - tOff,tOff);                         // upper right corner
        if (Alignment == SemiCircleAlignment.Left || Alignment == SemiCircleAlignment.Bottom)
        {
            endPt = new Point(tOff, ActualHeight - tOff);                         // or lower left corner
        }
        Size s = new Size(Math.Max(0.0,(ActualWidth / 2) - tOff), 
            Math.Max(0,ActualHeight - StrokeThickness));    // half width is radius
        SweepDirection sweep = SweepDirection.Counterclockwise;    
        if (Alignment == SemiCircleAlignment.Left || Alignment == SemiCircleAlignment.Right)
        {
            s = new Size(Math.Max(0,ActualWidth - StrokeThickness),
                Math.Max(0.0,(ActualHeight / 2) - tOff));     // or half height is radius
            sweep = SweepDirection.Clockwise;
        }
        context.BeginFigure(startPt, true, true);
        context.ArcTo(endPt, s, 0, false, sweep, true, false);
    }
}
public enum SemiCircleAlignment { Left, Top, Right, Bottom };