2012年4月20日星期五

WPF 之 自定义Shape

WPF 之 自定义Shape

AMindMap需要一个Line,用以连接父ANode和子ANode,

简单说,就是一头大一头小的线,Wpf自带的Line是没这个功能。

Path可以画,不过,我的想法仍旧是绑定。那只能自己做咯。

图例

image

正文

既然Line,Rectangle等都是继承自Shape的,直接新建一个类继承自Sharp.

 1 Public Class ALine 2     Inherits Shape 3  4     Protected Overrides ReadOnly Property DefiningGeometry As System.Windows.Media.Geometry 5         Get 6  7         End Get 8     End Property 9 End Class10 

继承完Shape,ALine中自动添加了一个需要重写的只读属性,从字面上就可以理解

为自定义shape的内容了。返回一个Geometry,那岂不是嗯嗯嗯?

ALine的属性

一头大一头小的Line也是Line,那就要有两个端点,并且,端点的数值是需要被

绑定的,大声一起说,“DependencyProperty”

  1   2 #Region "   X1  DependencyProperty "  3     ''' <summary>  4     ''' PropertyComment  5     ''' </summary>  6     ''' <remarks></remarks>  7     Public Shared ReadOnly X1Property As DependencyProperty = _  8         DependencyProperty.Register(  9             "X1", GetType(Double), GetType(ALine), New FrameworkPropertyMetadata( _ 10                 0.0, FrameworkPropertyMetadataOptions.AffectsMeasure)) 11  12     Public Property X1() As Double 13         Get 14             Return GetValue(X1Property) 15         End Get 16         Set(ByVal Value As Double) 17             SetValue(X1Property, Value) 18         End Set 19     End Property 20 #End Region 21  22 #Region "   Y1  DependencyProperty " 23     ''' <summary> 24     ''' PropertyComment 25     ''' </summary> 26     ''' <remarks></remarks> 27     Public Shared ReadOnly Y1Property As DependencyProperty = _ 28         DependencyProperty.Register( 29             "Y1", GetType(Double), GetType(ALine), New FrameworkPropertyMetadata( _ 30                 0.0, FrameworkPropertyMetadataOptions.AffectsMeasure)) 31  32     Public Property Y1() As Double 33         Get 34             Return GetValue(Y1Property) 35         End Get 36         Set(ByVal Value As Double) 37             SetValue(Y1Property, Value) 38         End Set 39     End Property 40  41 #End Region 42  43 #Region "   X2  DependencyProperty " 44     ''' <summary> 45     ''' PropertyComment 46     ''' </summary> 47     ''' <remarks></remarks> 48     Public Shared ReadOnly X2Property As DependencyProperty = _ 49         DependencyProperty.Register( 50             "X2", GetType(Double), GetType(ALine), New FrameworkPropertyMetadata( _ 51                 0.0, FrameworkPropertyMetadataOptions.AffectsMeasure)) 52  53     Public Property X2() As Double 54         Get 55             Return GetValue(X2Property) 56         End Get 57         Set(ByVal Value As Double) 58             SetValue(X2Property, Value) 59         End Set 60     End Property 61  62 #End Region 63  64 #Region "   Y2  DependencyProperty " 65     ''' <summary> 66     ''' PropertyComment 67     ''' </summary> 68     ''' <remarks></remarks> 69     Public Shared ReadOnly Y2Property As DependencyProperty = _ 70         DependencyProperty.Register( 71             "Y2", GetType(Double), GetType(ALine), New FrameworkPropertyMetadata( _ 72                 0.0, FrameworkPropertyMetadataOptions.AffectsMeasure)) 73  74     Public Property Y2() As Double 75         Get 76             Return GetValue(Y2Property) 77         End Get 78         Set(ByVal Value As Double) 79             SetValue(Y2Property, Value) 80         End Set 81     End Property 82  83 #End Region 84  85 #Region "   TailWidth  DependencyProperty " 86     ''' <summary> 87     ''' PropertyComment 88     ''' </summary> 89     ''' <remarks></remarks> 90     Public Shared ReadOnly TailWidthProperty As DependencyProperty = _ 91         DependencyProperty.Register( 92             "TailWidth", GetType(Double), GetType(ALine), New FrameworkPropertyMetadata( _ 93                 3.0, FrameworkPropertyMetadataOptions.AffectsMeasure)) 94     Public Property TailWidth() As Double 95         Get 96             Return GetValue(TailWidthProperty) 97         End Get 98         Set(ByVal Value As Double) 99             SetValue(TailWidthProperty, Value)100         End Set101     End Property102 103 #End Region

这里定义了X1,Y1,X2,Y2,TailWidth,这些属性足够说明,线的位置和尾部粗细。

ALine的内容

一个楔形是怎么画的呢?这只是一个几何问题,还是画一张图说明吧。

image

Sorry哈,反正就是Atan,sin,cos一通算,画图太费劲了,我就歇了哈。

代码 强制重载的DefiningGeometry
 1  2     Protected Overrides ReadOnly Property DefiningGeometry As System.Windows.Media.Geometry 3         Get 4             Dim mGeometry As New StreamGeometry 5             mGeometry.FillRule = FillRule.EvenOdd 6  7             Using context As StreamGeometryContext = mGeometry.Open 8                 DrawLineGeometry(context) 9             End Using10             mGeometry.Freeze()11             Return mGeometry12         End Get13     End Property14 15     Private Sub DrawLineGeometry(ByVal context As StreamGeometryContext)16         Dim theta As Double = Math.Atan2(Y1 - Y2, X1 - X2)17         Dim sint As Double = Math.Sin(theta)18         Dim cost As Double = Math.Cos(theta)19         Dim pt1 As Point = New Point(X2, Y2)20         Dim pt2 As Point = New Point(X1 - TailWidth * sint, Y1 + TailWidth * cost)21         Dim pt3 As Point = New Point(X1 + TailWidth * sint, Y1 - TailWidth * cost)22         context.BeginFigure(pt1, True, True)23         context.LineTo(pt2, True, True)24         context.LineTo(pt3, True, True)25     End Sub
实例

在一个空白窗口中,像使用Line一样。

1 <local:ALine X1="10" Y1="10" X2="100" Y2="100" TailWidth="10" 2              Fill="LightBlue" 3              Canvas.Left="93" Canvas.Top="76"4              >5 </local:ALine>

就这个效果

image

 

我不得不说,这个思路是在网上找到的,既然找到了,给大家分享一下,是一件好事儿。


TAG: