WPF Ellipse rotate via doubleanimation in mvvm

//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; }
    }
}

 

 

 

 

 

 

 

posted @ 2025-05-10 21:58  FredGrit  阅读(10)  评论(0)    收藏  举报