WPF Customize usercontrol rotate,mousedown,mouseup,mousemove

<UserControl x:Class="WpfApp68.UCRotatedElp"
             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:WpfApp68"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Ellipse 
                Width="{Binding UCElpWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
                Height="{Binding UCElpHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
                RenderTransformOrigin="0.5,0.5"
            StrokeThickness="5"
            Stroke="Red"
                >
            <Ellipse.Fill>
                <ImageBrush ImageSource="{Binding UCImgSource,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"/>
            </Ellipse.Fill>
            <Ellipse.RenderTransform>
                <RotateTransform Angle="{Binding UCRotatedAngle,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"/>
            </Ellipse.RenderTransform>             
        </Ellipse>
        <behavior:Interaction.Triggers>
            <behavior:EventTrigger EventName="MouseDown">
                <behavior:InvokeCommandAction 
                    Command="{Binding UCMouseDownCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}}"
                    PassEventArgsToCommand="True"/>
            </behavior:EventTrigger>
            <behavior:EventTrigger EventName="MouseMove">
                <behavior:InvokeCommandAction
                    Command="{Binding UCMouseMoveCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
                    PassEventArgsToCommand="True"/>
            </behavior:EventTrigger>
            <behavior:EventTrigger EventName="MouseUp">
                <behavior:InvokeCommandAction
                    Command="{Binding UCMouseUpCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"
                    PassEventArgsToCommand="True"/>
            </behavior:EventTrigger>
        </behavior:Interaction.Triggers>
    </Grid>
</UserControl>


//cs
using System;
using System.Collections.Generic;
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 WpfApp68
{
    /// <summary>
    /// Interaction logic for UCRotatedElp.xaml
    /// </summary>
    public partial class UCRotatedElp : UserControl
    {
        private FrameworkElement fe;
        public UCRotatedElp()
        {
            InitializeComponent(); 
        } 

        public double UCElpWidth
        {
            get { return (double)GetValue(UCElpWidthProperty); }
            set { SetValue(UCElpWidthProperty, value); }
        }

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




        public double UCElpHeight
        {
            get { return (double)GetValue(UCElpHeightProperty); }
            set { SetValue(UCElpHeightProperty, value); }
        }

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






        public ImageSource UCImgSource
        {
            get { return (ImageSource)GetValue(UCImgSourceProperty); }
            set { SetValue(UCImgSourceProperty, value); }
        }

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





        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(UCRotatedElp), new PropertyMetadata(0.0d));




        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(UCRotatedElp), 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(UCRotatedElp), 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(UCRotatedElp), new PropertyMetadata(null));



    }
}

 

 

//invoke

//xaml
<Window x:Class="WpfApp68.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:WpfApp68"
        WindowState="Maximized"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid> 
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <local:UCRotatedElp Grid.Row="0" Grid.Column="0"
                            UCElpHeight="{Binding ElpHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                            UCElpWidth="{Binding ElpWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                            UCImgSource="{Binding ImgSource1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                            UCMouseDownCommand="{Binding Elp1MouseDownCommand}"
                            UCMouseMoveCommand="{Binding Elp1MouseMoveCommand}"
                            UCMouseUpCommand="{Binding Elp1MouseUpCommand}"
                            UCRotatedAngle="{Binding Elp1RotatedAngle}"
                            />
        <TextBlock Text="{Binding Elp1RoatetedStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                   Grid.Column="0"
                   VerticalAlignment="Bottom"
                   HorizontalAlignment="Center"
                   FontSize="30"/>
        <local:UCRotatedElp Grid.Row="0"
                            Grid.Column="1"
                            UCElpHeight="400"
                            UCElpWidth="400"/>
    </Grid>
</Window>

//cs
using CommunityToolkit.Mvvm.ComponentModel;
using System.ComponentModel;
using System.IO;
using System.Runtime.CompilerServices;
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.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp68
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            var vm = new MainVM(this);
            this.DataContext=vm;
            this.SizeChanged+=(s, e) =>
            {
                vm.ElpWidth=this.ActualHeight/2;
                vm.ElpHeight=this.ActualHeight/2;
            };
        }
    }

    public partial class MainVM : ObservableObject
    {
        Window win;

        public ICommand Elp1MouseDownCommand { get; set; }
        public ICommand Elp1MouseMoveCommand { get; set; }
        public ICommand Elp1MouseUpCommand { get; set; }

        public MainVM(Window winVlaue)
        {
            win=winVlaue;
            string imgFile1 = @"pack://application:,,,/Images/1.jpg";
            ImgSource1 = GetImgSourceViaUrl(imgFile1);
            InitCommands();
        }

        private void InitCommands()
        {
            Elp1MouseDownCommand=new DelCommand(Elp1MouseDownCommandExecuted);
            Elp1MouseMoveCommand=new DelCommand(Elp1MouseMoveCommandExecuted);
            Elp1MouseUpCommand=new DelCommand(Elp1MouseUpCommandExecuted);
        }

        private Point elp1OriginPt;
        private Point elp1PrevPt;
        private void Elp1MouseUpCommandExecuted(object? obj)
        {
            if (Mouse.LeftButton==MouseButtonState.Released)
            {
                Mouse.Capture(null);
            }
        }

        private void Elp1MouseMoveCommandExecuted(object? obj)
        {
            if (Mouse.LeftButton==MouseButtonState.Pressed)
            {
                Vector prevVec = Point.Subtract(elp1PrevPt, elp1OriginPt);
                Point newPt = Mouse.GetPosition(win);
                Vector newVec = Point.Subtract(newPt, elp1OriginPt);
                double angleDelta = Vector.AngleBetween(prevVec,newVec);
                Elp1RotatedAngle+=angleDelta;
                elp1PrevPt=newPt;
                Elp1RoatetedStr=$"Rotated :{Elp1RotatedAngle.ToString()}";
            }
        }

        private void Elp1MouseDownCommandExecuted(object? obj)
        {
            if (obj is MouseButtonEventArgs e && Mouse.LeftButton==MouseButtonState.Pressed)
            {                
                elp1OriginPt= new Point(win.ActualWidth/4, win.ActualHeight/4);
                elp1PrevPt=Mouse.GetPosition(win);

                var elp = e.Source as Ellipse;
                if(elp!=null)
                {
                    Mouse.Capture(elp);
                }
            }
        }

        private void Win_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            var fe = win.Content as FrameworkElement;
            if (fe!=null)
            {
                ElpWidth=fe.ActualHeight/2;
                ElpHeight=fe.ActualHeight/2;
                string imgFile1 = @"pack://application:,,,/Images/1.jpg";
                ImgSource1=GetImgSourceViaUrl(imgFile1);
            }
        }

        private ImageSource GetImgSourceViaUrl(string imgUrl)
        {
            BitmapImage bmi = new BitmapImage();
            bmi.BeginInit();
            bmi.UriSource=new Uri(imgUrl);
            bmi.EndInit();
            if (bmi.CanFreeze)
            {
                bmi.Freeze();
            }
            return bmi;
        }

        [ObservableProperty]
        private double elpWidth;

        [ObservableProperty]
        private double elpHeight;

        [ObservableProperty]
        private ImageSource imgSource1;

        [ObservableProperty]
        private double elp1RotatedAngle;

        [ObservableProperty]
        private string elp1RoatetedStr;
    }

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

        public event EventHandler? CanExecuteChanged
        {
            add
            {
                CommandManager.RequerySuggested+=value;
            }
            remove
            {
                CommandManager.RequerySuggested -=value;
            }
        }

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

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

 

 

 

image

 

 

 

image

 

 

 

 

 

 

 

 

 

image

 

posted @ 2025-09-04 12:12  FredGrit  阅读(6)  评论(0)    收藏  举报