wpf自定义控件-单/双箭头线

using System;

using System.ComponentModel;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

using System.Windows.Shapes;

namespace CustomControls

{

TypeDescriptionProvider(typeof(CustomTypeDescriptionProvider))

public class CustomArrow : Shape

{

public CustomArrow ()

{

Stroke= new SolidColorBrush(Color.FromRgb(0, 140, 206));

}

#region Dependency Properties

复制代码
    public static readonly DependencyProperty X1Property = DependencyProperty.Register("X1", typeof(double), typeof(BvArrow), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
    public static readonly DependencyProperty Y1Property = DependencyProperty.Register("Y1", typeof(double), typeof(BvArrow), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
    public static readonly DependencyProperty X2Property = DependencyProperty.Register("X2", typeof(double), typeof(BvArrow), new FrameworkPropertyMetadata(150.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
    public static readonly DependencyProperty Y2Property = DependencyProperty.Register("Y2", typeof(double), typeof(BvArrow), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
    public static readonly DependencyProperty HeadWidthProperty = DependencyProperty.Register("HeadWidth", typeof(double), typeof(BvArrow), new FrameworkPropertyMetadata(15.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
    public static readonly DependencyProperty HeadHeightProperty = DependencyProperty.Register("HeadHeight", typeof(double), typeof(BvArrow), new FrameworkPropertyMetadata(5.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
    public static readonly DependencyProperty IsBidirectionalProperty = DependencyProperty.Register("IsBidirectional", typeof(bool), typeof(BvArrow), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));

    #endregion

    #region CLR Properties
    [Browsable(true)]
    public bool IsBidirectional
    {
        get
        {
            return (bool)GetValue(IsBidirectionalProperty);
        }
        set
        {
            SetValue(IsBidirectionalProperty, value);
        }
    }

    [Browsable(true)]
    public new Brush Stroke
    {
        get 
        { 
            return (Brush)GetValue(StrokeProperty); 
        }
        set
        {
            SetValue(StrokeProperty, value);
        }
    }
    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public new double StrokeThickness
    {
        get
        {
            return (double)GetValue(StrokeThicknessProperty);
        }
        set
        {
            SetValue(StrokeThicknessProperty, value);
        }
    }

    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public double X1
    {
        get { return (double)base.GetValue(X1Property); }
        set { base.SetValue(X1Property, value); }
    }

    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public double Y1
    {
        get { return (double)base.GetValue(Y1Property); }
        set { base.SetValue(Y1Property, value); }
    }

    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public double X2
    {
        get { return (double)base.GetValue(X2Property); }
        set { base.SetValue(X2Property, value); }
    }

    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public double Y2
    {
        get { return (double)base.GetValue(Y2Property); }
        set { base.SetValue(Y2Property, value); }
    }

    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public double HeadWidth
    {
        get { return (double)base.GetValue(HeadWidthProperty); }
        set { base.SetValue(HeadWidthProperty, value); }
    }

    [Browsable(true)]
    [TypeConverter(typeof(LengthConverter))]
    public double HeadHeight
    {
        get { return (double)base.GetValue(HeadHeightProperty); }
        set { base.SetValue(HeadHeightProperty, value); }
    }

    #endregion

    #region Overrides

    protected override Geometry DefiningGeometry
    {
        get
        {
            // Create a StreamGeometry for describing the shape
            StreamGeometry geometry = new StreamGeometry();
            geometry.FillRule = FillRule.EvenOdd;

            using (StreamGeometryContext context = geometry.Open())
            {
                InternalDrawArrowGeometry(context);
            }

            // Freeze the geometry for performance benefits
            geometry.Freeze();

            return geometry;
        }
    }

    #endregion

    #region Privates

    private void InternalDrawArrowGeometry(StreamGeometryContext context)
    {
        double theta = Math.Atan2(Y1 - Y2, X1 - X2);
        double sint = Math.Sin(theta);
        double cost = Math.Cos(theta);

        Point pt1 = new Point(X1, this.Y1);
        Point pt2 = new Point(X2, this.Y2);
        if(IsBidirectional)
        {
            Point pt3 = new Point(
             X1 - (HeadWidth * cost - HeadHeight * sint),
             Y1 - (HeadWidth * sint + HeadHeight * cost));

            Point pt4 = new Point(
                X1 - (HeadWidth * cost + HeadHeight * sint),
                Y1 + (HeadHeight * cost - HeadWidth * sint));

            Point pt5 = new Point(
            X2 + (HeadWidth * cost - HeadHeight * sint),
            Y2 + (HeadWidth * sint + HeadHeight * cost));

            Point pt6 = new Point(
                X2 + (HeadWidth * cost + HeadHeight * sint),
                Y2 - (HeadHeight * cost - HeadWidth * sint));

            context.BeginFigure(pt1, true, false);
            context.LineTo(pt3, true, true);
            context.LineTo(pt1, false, true);
            context.LineTo(pt4, false, true);
            context.LineTo(pt1, true, true);
            context.LineTo(pt2, true, true);
            context.LineTo(pt5, true, true);
            context.LineTo(pt2, false, true);
            context.LineTo(pt6, true, true);
        }
        else
        {
            Point pt3 = new Point(
            X2 + (HeadWidth * cost - HeadHeight * sint),
            Y2 + (HeadWidth * sint + HeadHeight * cost));

            Point pt4 = new Point(
                X2 + (HeadWidth * cost + HeadHeight * sint),
                Y2 - (HeadHeight * cost - HeadWidth * sint));

            context.BeginFigure(pt1, true, false);
            context.LineTo(pt2, true, true);
            context.LineTo(pt3, true, true);
            context.LineTo(pt2, false, true);
            context.LineTo(pt4, true, true);
        }
    }
    #endregion
}

}

相关推荐
heimeiyingwang11 小时前
【架构实战】状态机架构:订单/工单状态流转设计
观察者模式·架构·wpf
KmSH8umpK2 天前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第三篇
redis·分布式·wpf
KmSH8umpK2 天前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案
redis·分布式·wpf
武藤一雄2 天前
WPF:MessageBox系统消息框
前端·microsoft·c#·.net·wpf
武藤一雄2 天前
WPF进阶:万字详解WPF如何性能优化
windows·性能优化·c#·.net·wpf·.netcore·鲁棒性
wangnaisheng2 天前
【WPF】路由事件详细使用
wpf
雨浓YN3 天前
GKMLT通讯工具箱(WPF MVVM) - 07-倍福ADS通讯
网络·wpf
雨浓YN3 天前
GKMLT通讯工具箱(WPF MVVM) - 04-三菱MC通讯
wpf
不会编程的懒洋洋3 天前
WPF XAML+布局+控件
xml·开发语言·c#·视觉检测·wpf·机器视觉·视图
雨浓YN3 天前
GKMLT通讯工具箱(WPF MVVM) - 06-OPCUA通讯
wpf