WPF Rotated Ellipse as usercontrol and reuse in window

//usercontrol.xaml
<UserControl x:Class="WpfApp163.UCRotateElp"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:behavior="http://schemas.microsoft.com/xaml/behaviors"
             xmlns:local="clr-namespace:WpfApp163"
             mc:Ignorable="d" 
             Width="Auto"
             Height="Auto">
    <UserControl.Resources>
        <local:SizeConverter x:Key="sizeConverter"/>
    </UserControl.Resources>
    <Grid>        
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="8*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0"
                   FontSize="20"
                   FontWeight="Bold"
                   Foreground="Red"
                   HorizontalAlignment="Center"
                   Text="{Binding UCRotatedAngleStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
        <Ellipse x:Name="ucElp"
                 Grid.Row="1"
                 RenderTransformOrigin="0.5,0.5"
                 Width="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,
                 AncestorType={x:Type Window}},
                 Converter={StaticResource sizeConverter},ConverterParameter=2.5}"
                 Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,
                 AncestorType={x:Type Window}},
                 Converter={StaticResource sizeConverter},ConverterParameter=2.5}"
                 >
            <Ellipse.Fill>
                <ImageBrush ImageSource="{Binding UCElpImgSource,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            </Ellipse.Fill>
            <behavior:Interaction.Triggers>
                <behavior:EventTrigger EventName="MouseDown">
                    <behavior:InvokeCommandAction Command="{Binding UCMouseDownCommand}"
                                                  CommandParameter="{Binding ElementName=ucElp}"/>
                </behavior:EventTrigger>
                <behavior:EventTrigger EventName="MouseMove">
                    <behavior:InvokeCommandAction Command="{Binding UCMouseMoveCommand}"
                                                  CommandParameter="{Binding ElementName=ucElp}"/>
                </behavior:EventTrigger>
                <behavior:EventTrigger EventName="MouseUp">
                    <behavior:InvokeCommandAction Command="{Binding UCMouseUpCommand}"
                                                  CommandParameter="{Binding ElementName=ucElp}"/>
                </behavior:EventTrigger>
            </behavior:Interaction.Triggers>
            <Ellipse.RenderTransform>
                <RotateTransform Angle="{Binding UCRotatedAngle,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
            </Ellipse.RenderTransform>
        </Ellipse>
    </Grid>
</UserControl>



//usercontrol.xaml.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp163
{
    /// <summary>
    /// Interaction logic for UCRotateElp.xaml
    /// </summary>
    public partial class UCRotateElp : UserControl
    {
        public UCRotateElp()
        {
            InitializeComponent();
            this.DataContext = this;
        }




        public string UCRotatedAngleStr
        {
            get { return (string)GetValue(UCRotatedAngleStrProperty); }
            set { SetValue(UCRotatedAngleStrProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UCRotatedAngleStr.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UCRotatedAngleStrProperty =
            DependencyProperty.Register("UCRotatedAngleStr", typeof(string),
                typeof(UCRotateElp), new PropertyMetadata(""));






        public double UCRotatedAngle
        {
            get { return (double)GetValue(UCRotatedAngleProperty); }
            set { SetValue(UCRotatedAngleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UCRotatedAngle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UCRotatedAngleProperty =
            DependencyProperty.Register("UCRotatedAngle", typeof(double),
                typeof(UCRotateElp), new PropertyMetadata(0.0d));







        public ImageSource UCElpImgSource
        {
            get { return (ImageSource)GetValue(UCElpImgSourceProperty); }
            set { SetValue(UCElpImgSourceProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UCElpImgSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UCElpImgSourceProperty =
            DependencyProperty.Register("UCElpImgSource", typeof(ImageSource),
                typeof(UCRotateElp), new PropertyMetadata(null));





        public ICommand UCMouseDownCommand
        {
            get { return (ICommand)GetValue(UCMouseDownCommandProperty); }
            set { SetValue(UCMouseDownCommandProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UCMouseDownCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UCMouseDownCommandProperty =
            DependencyProperty.Register("UCMouseDownCommand", typeof(ICommand),
                typeof(UCRotateElp), new PropertyMetadata(null));







        public ICommand UCMouseMoveCommand
        {
            get { return (ICommand)GetValue(UCMouseMoveCommandProperty); }
            set { SetValue(UCMouseMoveCommandProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UCMouseMoveCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UCMouseMoveCommandProperty =
            DependencyProperty.Register("UCMouseMoveCommand", typeof(ICommand),
                typeof(UCRotateElp), new PropertyMetadata(null));







        public ICommand UCMouseUpCommand
        {
            get { return (ICommand)GetValue(UCMouseUpCommandProperty); }
            set { SetValue(UCMouseUpCommandProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UCMouseUpCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UCMouseUpCommandProperty =
            DependencyProperty.Register("UCMouseUpCommand", typeof(ICommand),
                typeof(UCRotateElp), new PropertyMetadata(null));



    }

    public class SizeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            double dValue, dPara = 0;
            if (double.TryParse(value?.ToString(), out dValue) && 
                double.TryParse(parameter?.ToString(), out dPara))
            {
                return dValue / dPara;
            }
            return 0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }


    public class DelCommand : ICommand
    {
        public event EventHandler CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                CommandManager.RequerySuggested -= value;
            }
        }

        private Action<object> execute;
        private Predicate<object> canExecute;
        public DelCommand(Action<object> executeValue, Predicate<object> canExecuteValue = null)
        {
            execute = executeValue;
            canExecute = canExecuteValue;
        }

        public bool CanExecute(object parameter)
        {
            if (canExecute == null)
            {
                return true;
            }
            return canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            execute(parameter);
        }
    }
}



//window.xaml
<Window x:Class="WpfApp163.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:WpfApp163"
        mc:Ignorable="d"
        WindowState="Maximized"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <local:UCRotateElp
            x:Name="firstRotateElp"
            Grid.Row="0"
            Grid.Column="0"
            UCMouseDownCommand="{Binding DataContext.FirstMouseDownCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCMouseMoveCommand="{Binding DataContext.FirstMouseMoveCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCMouseUpCommand="{Binding DataContext.FirstMouseUpCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCElpImgSource="{Binding DataContext.FirstImgSource,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCRotatedAngle="{Binding DataContext.FirstRotatedAngle,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCRotatedAngleStr="{Binding DataContext.FirstRotatedAngleStr,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>

        <local:UCRotateElp
            x:Name="secondRotateElp"
            Grid.Row="0"
            Grid.Column="1"
            UCMouseDownCommand="{Binding DataContext.SecondMouseDownCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCMouseMoveCommand="{Binding DataContext.SecondMouseMoveCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCMouseUpCommand="{Binding DataContext.SecondMouseUpCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCElpImgSource="{Binding DataContext.SecondImgSource,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCRotatedAngle="{Binding DataContext.SecondRotatedAngle,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCRotatedAngleStr="{Binding DataContext.SecondRotatedAngleStr,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>

        <local:UCRotateElp
            x:Name="thirdRotateElp"
            Grid.Row="1"
            Grid.Column="0"
            UCMouseDownCommand="{Binding DataContext.ThirdMouseDownCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCMouseMoveCommand="{Binding DataContext.ThirdMouseMoveCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCMouseUpCommand="{Binding DataContext.ThirdMouseUpCommand,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCElpImgSource="{Binding DataContext.ThirdImgSource,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCRotatedAngle="{Binding DataContext.ThirdRotatedAngle,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
            UCRotatedAngleStr="{Binding DataContext.ThirdRotatedAngleStr,
            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>

        <local:UCRotateElp
    x:Name="forthRotateElp"
    Grid.Row="1"
    Grid.Column="1"
    UCMouseDownCommand="{Binding DataContext.ForthMouseDownCommand,
    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
    UCMouseMoveCommand="{Binding DataContext.ForthMouseMoveCommand,
    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
    UCMouseUpCommand="{Binding DataContext.ForthMouseUpCommand,
    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
    UCElpImgSource="{Binding DataContext.ForthImgSource,
    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
    UCRotatedAngle="{Binding DataContext.ForthRotatedAngle,
    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"            
    UCRotatedAngleStr="{Binding DataContext.ForthRotatedAngleStr,
    RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Window}}}"/>

    </Grid>
</Window>


//window.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;

namespace WpfApp163
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Closed += MainWindow_Closed;
            var vm = new MainVM(this);
            this.DataContext = vm;
        }

        private void MainWindow_Closed(object sender, EventArgs e)
        {
            Application.Current?.Shutdown();
        }
    }


    public class MainVM : INotifyPropertyChanged
    {

        Window win;
        public MainVM(Window winValue)
        {
            win = winValue;
            win.SizeChanged += Win_SizeChanged;
        }

        private void Win_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            InitFirstElp();
            InitSecondElp();
            InitThirdElp();
            InitForthElp();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
        }


        private ImageSource GetImgSourceViaUrl(string imgUrl)
        {
            if (!File.Exists(imgUrl))
            {
                return null;
            }
            BitmapImage bmi = new BitmapImage();
            bmi.BeginInit();
            bmi.UriSource = new Uri(imgUrl, UriKind.RelativeOrAbsolute);
            bmi.EndInit();
            if (bmi.CanFreeze)
            {
                bmi.Freeze();
            }
            return bmi;
        }

        #region FirstUCElp
        private UCRotateElp firstRotateElp { get; set; }
        private Ellipse firstElp { get; set; }
        private Point firstPrevPt { get; set; }
        private Point firstOriginPt { get; set; }

        public ICommand FirstMouseDownCommand { get; set; }
        public ICommand FirstMouseMoveCommand { get; set; }
        public ICommand FirstMouseUpCommand { get; set; }

        private double firstRotatedAngle;

        public double FirstRotatedAngle
        {
            get
            {   
                return firstRotatedAngle;
            }
            set
            {
                if(value!=firstRotatedAngle)
                {
                    firstRotatedAngle = value;
                    OnPropertyChanged(nameof(FirstRotatedAngle));
                }
            }
        }

        private string firstRotatedAngleStr;
        public string FirstRotatedAngleStr
        {
            get
            {
                return firstRotatedAngleStr;
            }
            set
            {
                if (value != firstRotatedAngleStr)
                {
                    firstRotatedAngleStr = value;
                    OnPropertyChanged($"{nameof(FirstRotatedAngleStr)}");
                }
            }
        }

        public ImageSource FirstImgSource { get; set; }
        private void InitFirstElp()
        {
            FirstImgSource = GetImgSourceViaUrl(@"../../Images/1.jpg");
            FirstMouseDownCommand = new DelCommand(FirstMouseDownCommandExecuted);
            FirstMouseMoveCommand = new DelCommand(FirstMouseMoveCommandExecuted);
            FirstMouseUpCommand = new DelCommand(FirstMouseUpCommandExecuted);

            var firstRotateElpTemp = win.FindName("firstRotateElp") as UCRotateElp;
            if (firstRotateElpTemp != null)
            {
                firstRotateElp = firstRotateElpTemp;
                var firstElpTemp = firstRotateElp.FindName("ucElp") as Ellipse;
                if (firstElpTemp != null)
                {
                    firstElp = firstElpTemp;
                    Point firstOriginPtTemp = new Point(firstElp.ActualWidth / 2, firstElp.ActualHeight / 2);
                    firstOriginPt = firstElp.TranslatePoint(firstOriginPtTemp, win);
                }
            }           
        }
        
        private void FirstMouseDownCommandExecuted(object obj)
        {
            if(Mouse.LeftButton==MouseButtonState.Pressed)
            {
                firstPrevPt = Mouse.GetPosition(win);
                firstElp.CaptureMouse();
            }
        }

        private void FirstMouseMoveCommandExecuted(object obj)
        {
            if(Mouse.LeftButton ==MouseButtonState.Pressed)
            {
                Vector firstPrevVec = Point.Subtract(firstPrevPt, firstOriginPt);
                Point newPt=Mouse.GetPosition(win);
                Vector firstNewVec = Point.Subtract(newPt, firstOriginPt);
                double deltaAngle=Vector.AngleBetween(firstPrevVec, firstNewVec);
                FirstRotatedAngle += deltaAngle;
                FirstRotatedAngleStr=Math.Round(FirstRotatedAngle,2).ToString();
                firstPrevPt = newPt;
            }
        }

        private void FirstMouseUpCommandExecuted(object obj)
        {
            if(Mouse.LeftButton ==MouseButtonState.Released)
            {
                firstElp.ReleaseMouseCapture();
            }
        }


        #endregion


        #region SecondUCElp
        private UCRotateElp secondRotateElp { get; set; }
        private Ellipse secondElp { get; set; }
        private Point secondPrevPt { get; set; }
        private Point secondOriginPt { get; set; }

        public ICommand SecondMouseDownCommand { get; set; }
        public ICommand SecondMouseMoveCommand { get; set; }
        public ICommand SecondMouseUpCommand { get; set; }

        private double secondRotatedAngle;

        public double SecondRotatedAngle
        {
            get
            {
                return secondRotatedAngle;
            }
            set
            {
                if (value != secondRotatedAngle)
                {
                    secondRotatedAngle = value;
                    OnPropertyChanged(nameof(SecondRotatedAngle));
                }
            }
        }

        private string secondRotatedAngleStr;
        public string SecondRotatedAngleStr
        {
            get
            {
                return secondRotatedAngleStr;
            }
            set
            {
                if (value != secondRotatedAngleStr)
                {
                    secondRotatedAngleStr = value;
                    OnPropertyChanged($"{nameof(SecondRotatedAngleStr)}");
                }
            }
        }

        public ImageSource SecondImgSource { get; set; }
        private void InitSecondElp()
        {
            SecondImgSource = GetImgSourceViaUrl(@"../../Images/2.jpg");
            SecondMouseDownCommand = new DelCommand(SecondMouseDownCommandExecuted);
            SecondMouseMoveCommand = new DelCommand(SecondMouseMoveCommandExecuted);
            SecondMouseUpCommand = new DelCommand(SecondMouseUpCommandExecuted);

            var secondRotateElpTemp = win.FindName("secondRotateElp") as UCRotateElp;
            if (secondRotateElpTemp != null)
            {
                secondRotateElp = secondRotateElpTemp;
                var secondElpTemp = secondRotateElp.FindName("ucElp") as Ellipse;
                if (secondElpTemp != null)
                {
                    secondElp = secondElpTemp;
                    Point secondOriginPtTemp = new Point(secondElp.ActualWidth / 2, secondElp.ActualHeight / 2);
                    secondOriginPt = secondElp.TranslatePoint(secondOriginPtTemp, win);
                }
            }
        }

        private void SecondMouseDownCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                secondPrevPt = Mouse.GetPosition(win);
                secondElp.CaptureMouse();
            }
        }

        private void SecondMouseMoveCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                Vector secondPrevVec = Point.Subtract(secondPrevPt, secondOriginPt);
                Point newPt = Mouse.GetPosition(win);
                Vector secondNewVec = Point.Subtract(newPt, secondOriginPt);
                double deltaAngle = Vector.AngleBetween(secondPrevVec, secondNewVec);
                SecondRotatedAngle += deltaAngle;
                SecondRotatedAngleStr = Math.Round(SecondRotatedAngle, 2).ToString();
                secondPrevPt = newPt;
            }
        }

        private void SecondMouseUpCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Released)
            {
                secondElp.ReleaseMouseCapture();
            }
        }


        #endregion


        #region ThirdUCElp
        private UCRotateElp thirdRotateElp { get; set; }
        private Ellipse thirdElp { get; set; }
        private Point thirdPrevPt { get; set; }
        private Point thirdOriginPt { get; set; }

        public ICommand ThirdMouseDownCommand { get; set; }
        public ICommand ThirdMouseMoveCommand { get; set; }
        public ICommand ThirdMouseUpCommand { get; set; }

        private double thirdRotatedAngle;

        public double ThirdRotatedAngle
        {
            get
            {
                return thirdRotatedAngle;
            }
            set
            {
                if (value != thirdRotatedAngle)
                {
                    thirdRotatedAngle = value;
                    OnPropertyChanged(nameof(ThirdRotatedAngle));
                }
            }
        }

        private string thirdRotatedAngleStr;
        public string ThirdRotatedAngleStr
        {
            get
            {
                return thirdRotatedAngleStr;
            }
            set
            {
                if (value != thirdRotatedAngleStr)
                {
                    thirdRotatedAngleStr = value;
                    OnPropertyChanged($"{nameof(ThirdRotatedAngleStr)}");
                }
            }
        }

        public ImageSource ThirdImgSource { get; set; }
        private void InitThirdElp()
        {
            ThirdImgSource = GetImgSourceViaUrl(@"../../Images/3.jpg");
            ThirdMouseDownCommand = new DelCommand(ThirdMouseDownCommandExecuted);
            ThirdMouseMoveCommand = new DelCommand(ThirdMouseMoveCommandExecuted);
            ThirdMouseUpCommand = new DelCommand(ThirdMouseUpCommandExecuted);

            var thirdRotateElpTemp = win.FindName("thirdRotateElp") as UCRotateElp;
            if (thirdRotateElpTemp != null)
            {
                thirdRotateElp = thirdRotateElpTemp;
                var thirdElpTemp = thirdRotateElp.FindName("ucElp") as Ellipse;
                if (thirdElpTemp != null)
                {
                    thirdElp = thirdElpTemp;
                    Point thirdOriginPtTemp = new Point(thirdElp.ActualWidth / 2, thirdElp.ActualHeight / 2);
                    thirdOriginPt = thirdElp.TranslatePoint(thirdOriginPtTemp, win);
                }
            }
        }

        private void ThirdMouseDownCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                thirdPrevPt = Mouse.GetPosition(win);
                thirdElp.CaptureMouse();
            }
        }

        private void ThirdMouseMoveCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                Vector thirdPrevVec = Point.Subtract(thirdPrevPt, thirdOriginPt);
                Point newPt = Mouse.GetPosition(win);
                Vector thirdNewVec = Point.Subtract(newPt, thirdOriginPt);
                double deltaAngle = Vector.AngleBetween(thirdPrevVec, thirdNewVec);
                ThirdRotatedAngle += deltaAngle;
                ThirdRotatedAngleStr = Math.Round(ThirdRotatedAngle, 2).ToString();
                thirdPrevPt = newPt;
            }
        }

        private void ThirdMouseUpCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Released)
            {
                thirdElp.ReleaseMouseCapture();
            }
        }


        #endregion


        #region ForthUCElp
        private UCRotateElp forthRotateElp { get; set; }
        private Ellipse forthElp { get; set; }
        private Point forthPrevPt { get; set; }
        private Point forthOriginPt { get; set; }

        public ICommand ForthMouseDownCommand { get; set; }
        public ICommand ForthMouseMoveCommand { get; set; }
        public ICommand ForthMouseUpCommand { get; set; }

        private double forthRotatedAngle;

        public double ForthRotatedAngle
        {
            get
            {
                return forthRotatedAngle;
            }
            set
            {
                if (value != forthRotatedAngle)
                {
                    forthRotatedAngle = value;
                    OnPropertyChanged(nameof(ForthRotatedAngle));
                }
            }
        }

        private string forthRotatedAngleStr;
        public string ForthRotatedAngleStr
        {
            get
            {
                return forthRotatedAngleStr;
            }
            set
            {
                if (value != forthRotatedAngleStr)
                {
                    forthRotatedAngleStr = value;
                    OnPropertyChanged($"{nameof(ForthRotatedAngleStr)}");
                }
            }
        }

        public ImageSource ForthImgSource { get; set; }
        private void InitForthElp()
        {
            ForthImgSource = GetImgSourceViaUrl(@"../../Images/4.jpg");
            ForthMouseDownCommand = new DelCommand(ForthMouseDownCommandExecuted);
            ForthMouseMoveCommand = new DelCommand(ForthMouseMoveCommandExecuted);
            ForthMouseUpCommand = new DelCommand(ForthMouseUpCommandExecuted);

            var forthRotateElpTemp = win.FindName("forthRotateElp") as UCRotateElp;
            if (forthRotateElpTemp != null)
            {
                forthRotateElp = forthRotateElpTemp;
                var forthElpTemp = forthRotateElp.FindName("ucElp") as Ellipse;
                if (forthElpTemp != null)
                {
                    forthElp = forthElpTemp;
                    Point forthOriginPtTemp = new Point(forthElp.ActualWidth / 2, forthElp.ActualHeight / 2);
                    forthOriginPt = forthElp.TranslatePoint(forthOriginPtTemp, win);
                }
            }
        }

        private void ForthMouseDownCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                forthPrevPt = Mouse.GetPosition(win);
                forthElp.CaptureMouse();
            }
        }

        private void ForthMouseMoveCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)
            {
                Vector forthPrevVec = Point.Subtract(forthPrevPt, forthOriginPt);
                Point newPt = Mouse.GetPosition(win);
                Vector forthNewVec = Point.Subtract(newPt, forthOriginPt);
                double deltaAngle = Vector.AngleBetween(forthPrevVec, forthNewVec);
                ForthRotatedAngle += deltaAngle;
                ForthRotatedAngleStr = Math.Round(ForthRotatedAngle, 2).ToString();
                forthPrevPt = newPt;
            }
        }

        private void ForthMouseUpCommandExecuted(object obj)
        {
            if (Mouse.LeftButton == MouseButtonState.Released)
            {
                forthElp.ReleaseMouseCapture();
            }
        }


        #endregion


    }
}

 

 

 

 

 

 

 

posted @ 2025-03-08 19:24  FredGrit  阅读(15)  评论(0)    收藏  举报