There's many different ways of doing this. Here is one, that may or may not meet your needs. It's just a user control. The radius of the circle is dependent on the size of the user control, and it will force the control to be uniform in size. Positioning the user control will be up to you. The angle of the inner line is bind-able.
User control xaml
<UserControl x:Class="TestWPF.CircleTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Foreground="Blue" Background="White"
x:Name="CT" SnapsToDevicePixels="True">
<Grid>
<Ellipse Stroke="{Binding Foreground, ElementName=CT}" Fill="{Binding Background, ElementName=CT}" />
<Line X1="{Binding Center.X, ElementName=CT}" X2="{Binding EndPoint.X, ElementName=CT}" Y1="{Binding Center.Y, ElementName=CT}" Y2="{Binding EndPoint.Y, ElementName=CT}"
Stroke="{Binding Foreground, ElementName=CT}">
<Line.RenderTransform>
<RotateTransform Angle="{Binding Angle, ElementName=CT}" CenterX="{Binding Center.X, ElementName=CT}" CenterY="{Binding Center.Y, ElementName=CT}" />
</Line.RenderTransform>
</Line>
<TextBlock Text="{Binding Angle, ElementName=CT, StringFormat='N2'}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="3" />
</Grid>
</UserControl>
User control code behind
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace TestWPF
{
public partial class CircleTest : UserControl, INotifyPropertyChanged
{
public CircleTest()
{
InitializeComponent();
this.SizeChanged += CircleTest_SizeChanged;
}
void CircleTest_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
double radius;
if (ActualHeight < ActualWidth)
{
Width = ActualHeight;
_center = new Point(Width / 2, ActualHeight / 2);
radius = ActualHeight / 2;
}
else
{
Height = ActualWidth;
_center = new Point(ActualWidth / 2, Height / 2);
radius = ActualWidth / 2;
}
_endPoint = new Point(Center.X, Center.Y - radius);
NotifyOfPropertyChange("Center");
NotifyOfPropertyChange("EndPoint");
}
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
public static readonly DependencyProperty AngleProperty = DependencyProperty.Register("Angle", typeof(double), typeof(CircleTest), new PropertyMetadata(45.0));
private Point _center;
public Point Center
{
get { return _center; }
}
private Point _endPoint;
public Point EndPoint
{
get { return _endPoint; }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyOfPropertyChange(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You'd use it like this:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:test="clr-namespace:TestWPF"
Title="MainWindow" Height="350" Width="525">
<Grid>
<test:CircleTest Width="200" Height="200" Foreground="Purple" Angle="{Binding Value, ElementName=SL}" />
<Slider x:Name="SL" Minimum="0" Maximum="360" VerticalAlignment="Bottom" Margin="20" />
</Grid>
</Window>