You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Polygon实现自定义Adorner:顶点装饰器适配方法求助

为Polygon顶点添加Adorner的完整实现方案

我完全懂你现在的困扰——官方文档的Adorner示例是针对普通元素的四个角,要套用到Polygon的每个顶点上确实有点绕。我给你把代码改好,直接就能用,还会讲清楚关键改动点。

第一步:修改Adorner类,适配Polygon顶点

原来的示例只画元素的四个边角,我们需要改成遍历Polygon的所有顶点来绘制Adorner:

public class PolygonVertexAdorner : Adorner
{
    private readonly Polygon _adornedPolygon;
    private readonly SolidColorBrush _fillBrush;
    private readonly Pen _borderPen;
    private const double AdornerRadius = 5.0;

    // 构造函数确保传入的是Polygon类型
    public PolygonVertexAdorner(UIElement adornedElement) : base(adornedElement)
    {
        _adornedPolygon = adornedElement as Polygon;
        if (_adornedPolygon == null)
            throw new ArgumentException("要添加Adorner的元素必须是Polygon类型");

        // 自定义Adorner的样式,你可以按需调整颜色、透明度
        _fillBrush = new SolidColorBrush(Colors.Green) { Opacity = 0.2 };
        _borderPen = new Pen(new SolidColorBrush(Colors.Navy), 1.5);
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);

        // 空值判断,避免NullReferenceException
        if (_adornedPolygon?.Points == null || _adornedPolygon.Points.Count == 0)
            return;

        // 获取坐标转换:把Polygon的局部顶点坐标转成Adorner坐标系下的位置
        Transform transform = _adornedPolygon.TransformToVisual(this);

        // 遍历每个顶点,绘制圆形Adorner
        foreach (Point vertex in _adornedPolygon.Points)
        {
            Point transformedPoint = transform.Transform(vertex);
            drawingContext.DrawEllipse(_fillBrush, _borderPen, transformedPoint, AdornerRadius, AdornerRadius);
        }
    }
}

第二步:修改你的Polygon绘制代码,添加Adorner

在你原来的drawPolygon方法里,最后加上添加Adorner的逻辑,确保Polygon创建后立刻带上顶点标记:

Polygon myPolygon;
private Polygon drawPolygon()
{
    //Add the Polygon Element
    myPolygon = new Polygon();
    // Appearance
    myPolygon.Stroke = System.Windows.Media.Brushes.LightCoral;
    // Disabled for hit testing on border only.
    //myPolygon.Fill = System.Windows.Media.Brushes.Transparent;
    myPolygon.StrokeThickness = 6;
    // Alignment
    myPolygon.HorizontalAlignment = HorizontalAlignment.Left;
    myPolygon.VerticalAlignment = VerticalAlignment.Center;
    // Point Array for polyline.
    // This will come from an XML file.
    Point[] polylinePoints = {
        // START: @ TOP LEFT
        new Point(200.0F, 200.0F),
        // 1ST LINE: TOP RIGHT
        new Point(400.0F, 200.0F),
        // 2ND LINE: BOMTTOM RIGHT
        new Point(400.0F, 400.0F),
        // 3RD LINE: BOTTOM LEFT
        new Point(200.0F, 400.0F),
        // END: @ TOP LEFT
        //Not Required to close the Polygon...
        //new Point(200.0F, 200.0F),
    };
    // Load from Point[Array] polylinePoints.
    PointCollection myPointCollection = new PointCollection(polylinePoints);
    //myPointCollection.Add(Point1);
    // Add from PointCollection myPointCollection
    myPolygon.Points = myPointCollection;

    // 关键:给当前Polygon添加顶点Adorner
    AttachVertexAdornerToPolygon(myPolygon);

    return myPolygon;
}

// 封装添加Adorner的方法,复用性更强
private void AttachVertexAdornerToPolygon(Polygon polygon)
{
    // 获取元素所在的AdornerLayer
    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(polygon);
    if (adornerLayer != null)
    {
        // 创建并添加自定义Adorner
        var vertexAdorner = new PolygonVertexAdorner(polygon);
        adornerLayer.Add(vertexAdorner);
    }
}

关键改动说明

  • 针对性适配Polygon:新的Adorner类会先验证传入的元素是Polygon,避免类型错误。
  • 坐标转换:用TransformToVisual把Polygon的局部顶点坐标转换成Adorner坐标系下的位置,确保Adorner精准出现在顶点上(就算Polygon有布局偏移也没问题)。
  • 空值安全:添加了多层空值判断,防止运行时抛出空引用异常。
  • 可复用性:把添加Adorner的逻辑封装成单独方法,以后给其他Polygon加Adorner直接调用就行。

内容的提问来源于stack exchange,提问作者suchislife801

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:52:15