/// <summary> /// Adds a line that connects the arc midpoint to the label and positions the label appropriately. /// Ideally, I would add the Polyline in the template and I would only change its points here. Unfortunately, /// because of a WPF bug, the Polyline doesn't render in certain corner-case scenarios. As a workaround, /// I create a new Polyline everytime the label is positioned, as can be seen in this method. /// </summary> private void PositionConnected() { try { this.RemovePolyline(); if (this.contentPart != null) { PointCollection newPoints = new PointCollection(); // First point newPoints.Add(this.SnapPoint(this.arcMidpoint)); // Second point Vector radialDirection = this.arcMidpoint - this.center; radialDirection.Normalize(); Point secondPoint = this.arcMidpoint + (radialDirection*10); newPoints.Add(this.SnapPoint(secondPoint)); // Third point int sign = Math.Sign(radialDirection.X); // 1 if label is on the right side, -1 if it's on the left. Point thirdPoint = secondPoint + new Vector(sign*20, 0); newPoints.Add(this.SnapPoint(thirdPoint)); double contentX = (sign == 1) ? thirdPoint.X : thirdPoint.X - this.contentPart.DesiredSize.Width; double contentY = thirdPoint.Y - 0.5*this.contentPart.DesiredSize.Height; Canvas.SetTop(this.contentPart, contentY); Canvas.SetLeft(this.contentPart, contentX); Polyline polyline = new Polyline(); polyline.Points = newPoints; polyline.SetBinding(Polyline.StrokeThicknessProperty, new Binding("LineStrokeThickness") {Source = this}); polyline.SetBinding(Polyline.StrokeProperty, new Binding("LineStroke") {Source = this}); polyline.StrokeLineJoin = PenLineJoin.Round; this.canvasPart.Children.Add(polyline); } } catch(Exception) { } }
private void SetPolylineBindings(Polyline polyline) { polyline.SetBinding(Polyline.StrokeProperty, new Binding { Source = this, Path = new PropertyPath("Stroke") }); polyline.SetBinding(Polyline.StrokeThicknessProperty, new Binding { Source = this, Path = new PropertyPath("StrokeThickness") }); }