WPF RotateCircle defines in usercontrol and reuse
//usercontrol //xaml <UserControl x:Class="WpfApp159.UCRotateCircle" 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:local="clr-namespace:WpfApp159" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Resources> <local:SizeConverter x:Key="sizeConverter"/> </UserControl.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="10*"/> </Grid.RowDefinitions> <TextBlock Grid.Row="0" FontSize="15" Foreground="Red" FontWeight="Bold" HorizontalAlignment="Center" Text="{Binding UCRotatedAngleStr,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/> <Ellipse x:Name="elp" Grid.Row="1" Width="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}, Converter={StaticResource sizeConverter}, ConverterParameter=2}" Height="{Binding ActualHeight,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type UserControl}}, Converter={StaticResource sizeConverter}, ConverterParameter=2}" MouseDown="elp_MouseDown" MouseMove="elp_MouseMove" MouseUp="elp_MouseUp" RenderTransformOrigin="0.5,0.5"> <Ellipse.RenderTransform> <RotateTransform x:Name="rotateTransform"/> </Ellipse.RenderTransform> <Ellipse.Fill> <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> <GradientStop Color="Orange" Offset="0.0"/> <GradientStop Color="Orange" Offset="0.2"/> <GradientStop Color="Yellow" Offset="0.2"/> <GradientStop Color="Yellow" Offset="0.4"/> <GradientStop Color="Green" Offset="0.4"/> <GradientStop Color="Green" Offset="0.499"/> <GradientStop Color="Red" Offset="0.499"/> <GradientStop Color="Red" Offset="0.501"/> <GradientStop Color="Green" Offset="0.501"/> <GradientStop Color="Green" Offset="0.6"/> <GradientStop Color="Cyan" Offset="0.6"/> <GradientStop Color="Cyan" Offset="0.8"/> <GradientStop Color="Blue" Offset="0.8"/> <GradientStop Color="Blue" Offset="1.0"/> </LinearGradientBrush> </Ellipse.Fill> </Ellipse> </Grid> </UserControl> //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 WpfApp159 { /// <summary> /// Interaction logic for UCRotateCircle.xaml /// </summary> public partial class UCRotateCircle : UserControl { public UCRotateCircle() { InitializeComponent(); this.DataContext = this; } Point originPt { get; set; } Point currentPt { get; set; } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { base.OnRenderSizeChanged(sizeInfo); Point tempPt=new Point(elp.ActualWidth/2, elp.ActualHeight/2); originPt = elp.TranslatePoint(tempPt, this); } public double UCConverterParameter { get { return (double)GetValue(UCConverterParameterProperty); } set { SetValue(UCConverterParameterProperty, value); } } // Using a DependencyProperty as the backing store for UCConverterParameter. This enables animation, styling, binding, etc... public static readonly DependencyProperty UCConverterParameterProperty = DependencyProperty.Register("UCConverterParameter", typeof(double), typeof(UCRotateCircle), new PropertyMetadata(2.0d)); 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(UCRotateCircle), new PropertyMetadata("0")); private void elp_MouseDown(object sender, MouseButtonEventArgs e) { if(e.LeftButton == MouseButtonState.Pressed) { currentPt=e.GetPosition(this); elp.CaptureMouse(); } } private void elp_MouseMove(object sender, MouseEventArgs e) { if(e.LeftButton== MouseButtonState.Pressed) { Vector prevVec=Point.Subtract(currentPt,originPt); Point newPt = e.GetPosition(this); Vector newVec=Point.Subtract(newPt,originPt); double deltaAngle=Vector.AngleBetween(prevVec, newVec); rotateTransform.Angle += deltaAngle; currentPt = newPt; UCRotatedAngleStr = Math.Round(rotateTransform.Angle, 2).ToString(); System.Diagnostics.Debug.WriteLine($"{deltaAngle},{rotateTransform.Angle}"); } } private void elp_MouseUp(object sender, MouseButtonEventArgs e) { if(e.LeftButton==MouseButtonState.Released) { elp.ReleaseMouseCapture(); } } } public class SizeConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { double dValue = 0.0, dPara = 0.0; if (double.TryParse(value?.ToString(), out dValue) && double.TryParse(parameter?.ToString(), out dPara) && dPara > 0) { return dValue / dPara; } return dValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } }
<Window x:Class="WpfApp159.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:WpfApp159" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <local:UCRotateCircle Grid.Row="0" Grid.Column="0"/> <local:UCRotateCircle Grid.Row="0" Grid.Column="1"/> <local:UCRotateCircle Grid.Row="1" Grid.Column="0"/> <local:UCRotateCircle Grid.Row="1" Grid.Column="1"/> </Grid> </Window>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现