//xaml
<Window x:Class="WpfApp7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp7"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Ellipse x:Name="elp"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="{Binding ElpWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Height="{Binding ElpHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
StrokeThickness="20"
RenderTransformOrigin="0.5,0.5">
<Ellipse.Stroke>
<LinearGradientBrush StartPoint="0,0"
EndPoint="1,1"
>
<GradientStop Color="Black" Offset="0.0"/>
<GradientStop Color="Red" Offset="0.1"/>
<GradientStop Color="Black" Offset="0.2"/>
<GradientStop Color="Red" Offset="0.3"/>
<GradientStop Color="Black" Offset="0.4"/>
<GradientStop Color="Red" Offset="0.5"/>
<GradientStop Color="Black" Offset="0.6"/>
<GradientStop Color="Red" Offset="0.7"/>
<GradientStop Color="Black" Offset="0.8"/>
<GradientStop Color="Red" Offset="0.9"/>
<GradientStop Color="Black" Offset="1.0"/>
</LinearGradientBrush>
</Ellipse.Stroke>
<Ellipse.Fill>
<ImageBrush ImageSource="{Binding ElpImgSource,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
</Ellipse.Fill>
<Ellipse.RenderTransform>
<RotateTransform x:Name="elpRotateTransform"/>
</Ellipse.RenderTransform>
</Ellipse>
<ItemsControl x:Name="ticksControl"
ItemsSource="{Binding TicksList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Line X1="{Binding StartX}"
Y1="{Binding StartY}"
X2="{Binding EndX}"
Y2="{Binding EndY}"
Stroke="{Binding TickStroke}"
StrokeThickness="{Binding TickStrokeThickness}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
//cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp7
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var vm = new MainVM(this);
this.DataContext = vm;
}
}
public class MainVM : INotifyPropertyChanged
{
private Window win;
private FrameworkElement fe;
private int ticksCount = 60;
private ItemsControl ticksControl;
private Ellipse elp;
private RotateTransform elpRotateTransform;
public MainVM(Window winValue)
{
win = winValue;
win.SizeChanged += Win_SizeChanged;
win.Loaded += Win_Loaded;
}
private void Win_Loaded(object sender, RoutedEventArgs e)
{
Init();
}
private void Win_SizeChanged(object sender, SizeChangedEventArgs e)
{
Init();
}
private void Init()
{
var tempFe = win.Content as FrameworkElement;
if (tempFe != null)
{
fe = tempFe;
CenterX = fe.ActualWidth / 2;
CenterY = fe.ActualHeight / 2;
TickRadius = Math.Min(fe.ActualWidth, fe.ActualHeight) / 2 - 50;
ElpHeight = fe.ActualHeight;
ElpWidth = fe.ActualHeight;
string imgUrl=@"../../../Images/10.jpg";
if(File.Exists(imgUrl))
{
ElpImgSource = new BitmapImage(new Uri(imgUrl, UriKind.RelativeOrAbsolute));
}
else
{
MessageBox.Show("Image not found!");
}
}
var tempTicksControl = win.FindName("ticksControl") as ItemsControl;
if (tempTicksControl != null)
{
ticksControl = tempTicksControl;
}
else
{
MessageBox.Show("TicksControl not found!");
}
var tempElp = win.FindName("elp") as Ellipse;
if (tempElp != null)
{
elp = tempElp;
}
else
{
MessageBox.Show("Ellipse not found!");
}
var tempElpRotateTransform = win.FindName("elpRotateTransform") as RotateTransform;
if (tempElpRotateTransform != null)
{
elpRotateTransform = tempElpRotateTransform;
}
else
{
MessageBox.Show("Ellipse RotateTransform not found!");
}
InitTicks();
InitElpRotationDoubleAnimation();
}
DoubleAnimation animation;
Storyboard animationBoard;
private void InitElpRotationDoubleAnimation()
{
animationBoard = new Storyboard();
animation = new DoubleAnimation();
animation.From = 0;
animation.To = 360;
animation.Duration = TimeSpan.FromSeconds(10);
animation.RepeatBehavior = RepeatBehavior.Forever;
elpRotateTransform.BeginAnimation(RotateTransform.AngleProperty, animation);
//Storyboard.SetTargetProperty(elp,new PropertyPath("(Ellipse.RenderTransform).(RotateTransform.Angle)"));
//Storyboard.SetTarget(animation, elp);
//animationBoard.Children.Add(animation);
//animationBoard.Begin();
}
private void InitTicks()
{
List<TickClass> ticksList = new List<TickClass>();
double angleStep = (double)(360.0 / ticksCount);
double tickLength = 30;
Brush tickStroke = Brushes.Black;
double tickStrokeThickness = 1;
for (int i = 0; i < ticksCount; i++)
{
tickLength = i % 5 == 0 ? 50 : 30;
tickStroke = i % 5 == 0 ? Brushes.Red : Brushes.Black;
tickStrokeThickness = i % 5 == 0 ? 3 : 1;
double angle = (double)(angleStep * i - 90);
ticksList.Add(new TickClass()
{
StartX = CenterX + TickRadius * Math.Cos((angle) * Math.PI / 180),
StartY = CenterY + TickRadius * Math.Sin((angle) * Math.PI / 180),
EndX = CenterX + (TickRadius + tickLength) * Math.Cos((angle) * Math.PI / 180),
EndY = CenterY + (TickRadius + tickLength) * Math.Sin((angle) * Math.PI / 180),
TickStroke = tickStroke,
TickStrokeThickness = tickStrokeThickness
});
}
TicksList = new ObservableCollection<TickClass>(ticksList);
}
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private ImageSource elpImgSource;
public ImageSource ElpImgSource
{
get
{
return elpImgSource;
}
set
{
if(value!= elpImgSource)
{
elpImgSource = value;
OnPropertyChanged(nameof(ElpImgSource));
}
}
}
private double elpWidth;
public double ElpWidth
{
get
{
return elpWidth;
}
set
{
if (value != elpWidth)
{
elpWidth = value;
OnPropertyChanged(nameof(ElpWidth));
}
}
}
private double elpHeight;
public double ElpHeight
{
get
{
return elpHeight;
}
set
{
if (value != elpHeight)
{
elpHeight = value;
OnPropertyChanged(nameof(ElpHeight));
}
}
}
private ObservableCollection<TickClass> ticksList;
public ObservableCollection<TickClass> TicksList
{
get
{
return ticksList;
}
set
{
if (value != ticksList)
{
ticksList = value;
OnPropertyChanged(nameof(TicksList));
}
}
}
private double centerX;
public double CenterX
{
get
{
return centerX;
}
set
{
if (value != centerX)
{
centerX = value;
OnPropertyChanged(nameof(CenterX));
}
}
}
private double centerY;
public double CenterY
{
get
{
return centerY;
}
set
{
if (value != centerY)
{
centerY = value;
OnPropertyChanged(nameof(CenterY));
}
}
}
private double tickRadius;
public double TickRadius
{
get
{
return tickRadius;
}
set
{
if (value != tickRadius)
{
tickRadius = value;
OnPropertyChanged(nameof(TickRadius));
}
}
}
}
public class TickClass
{
public double StartX { get; set; }
public double StartY { get; set; }
public double EndX { get; set; }
public double EndY { get; set; }
public Brush TickStroke { get; set; }
public double TickStrokeThickness { get; set; }
}
}
![]()
![]()
![]()