If I have the following four properties in my DataContext of my Canvas element
Point Center
double Radius
double StartAngle
double EndAngle
<
May I offer a slightly different solution?
class ArcII:FrameworkElement
{
///
/// Center point of Arc.
///
[Category("Arc")]
public Point Center
{
get { return (Point)GetValue(CenterProperty); }
set { SetValue(CenterProperty, value); }
}
// Using a DependencyProperty as the backing store for Center. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CenterProperty =
DependencyProperty.Register("Center", typeof(Point), typeof(ArcII), new FrameworkPropertyMetadata(new Point(0, 0), FrameworkPropertyMetadataOptions.AffectsRender));
///
/// Forces the Arc to the center of the Parent container.
///
[Category("Arc")]
public bool OverrideCenter
{
get { return (bool)GetValue(OverrideCenterProperty); }
set { SetValue(OverrideCenterProperty, value); }
}
// Using a DependencyProperty as the backing store for OverrideCenter. This enables animation, styling, binding, etc...
public static readonly DependencyProperty OverrideCenterProperty =
DependencyProperty.Register("OverrideCenter", typeof(bool), typeof(ArcII), new FrameworkPropertyMetadata((bool)false, FrameworkPropertyMetadataOptions.AffectsRender));
///
/// Start angle of arc, using standard coordinates. (Zero is right, CCW positive direction)
///
[Category("Arc")]
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
// Using a DependencyProperty as the backing store for StartAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
///
/// Length of Arc in degrees.
///
[Category("Arc")]
public double SweepAngle
{
get { return (double)GetValue(SweepAngleProperty); }
set { SetValue(SweepAngleProperty, value); }
}
// Using a DependencyProperty as the backing store for SweepAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SweepAngleProperty =
DependencyProperty.Register("SweepAngle", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata((double)180, FrameworkPropertyMetadataOptions.AffectsRender));
///
/// Size of Arc.
///
[Category("Arc")]
public double Radius
{
get { return (double)GetValue(RadiusProperty); }
set { SetValue(RadiusProperty, value); }
}
// Using a DependencyProperty as the backing store for Radius. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RadiusProperty =
DependencyProperty.Register("Radius", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));
[Category("Arc")]
public Brush Stroke
{
get { return (Brush)GetValue(StrokeProperty); }
set { SetValue(StrokeProperty, value); }
}
// Using a DependencyProperty as the backing store for Stroke. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StrokeProperty =
DependencyProperty.Register("Stroke", typeof(Brush), typeof(ArcII), new FrameworkPropertyMetadata((Brush)Brushes.Black,FrameworkPropertyMetadataOptions.AffectsRender));
[Category("Arc")]
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
// Using a DependencyProperty as the backing store for StrokeThickness. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StrokeThicknessProperty =
DependencyProperty.Register("StrokeThickness", typeof(double), typeof(ArcII), new FrameworkPropertyMetadata((double)1,FrameworkPropertyMetadataOptions.AffectsRender));
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
Draw(dc);
}
private void Draw(DrawingContext dc)
{
Point center = new Point();
if (OverrideCenter)
{
Rect rect = new Rect(RenderSize);
center = Polar.CenterPointFromRect(rect);
}
else
{
center = Center;
}
Point startPoint = Polar.PolarToCartesian(StartAngle, Radius, center);
Point endPoint = Polar.PolarToCartesian(StartAngle + SweepAngle, Radius, center);
Size size = new Size(Radius, Radius);
bool isLarge = (StartAngle + SweepAngle) - StartAngle > 180;
List segments = new List(1);
segments.Add(new ArcSegment(endPoint, new Size(Radius, Radius), 0.0, isLarge, SweepDirection.Clockwise, true));
List figures = new List(1);
PathFigure pf = new PathFigure(startPoint, segments, true);
pf.IsClosed = false;
figures.Add(pf);
Geometry g = new PathGeometry(figures, FillRule.EvenOdd, null);
dc.DrawGeometry(null, new Pen(Stroke,StrokeThickness), g);
}
}
Usage:
Notes: A) This will not do a 360 SweepAngle, for that use an ellipse. B) OverrideCenter: This puts the center of the Arc in the center of its parent. Note that elements like a Grid that can be partitioned, still have a center, which may not be the column or row the Arc is in.