我创建了一个自定义的圆形进度条,如下所示:
x1c 0d1x的数据
使用以下代码:
<UserControl x:Class="WpfApp1.SpinnerProgressBar"
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:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Viewbox>
<Canvas Width="100" Height="100">
<!-- Base Spinner -->
<Path Stroke="LightGray" StrokeThickness="3" Fill="LightGray"
Data="M 0 100 a 100,100 0 1 1 200,0
a 100,100 0 1 1 -200,0
M 30 100 a 70,70 0 1 1 140,0
a 70,70 0 1 1 -140,0" RenderTransformOrigin="0.5,0.5" />
<!-- Loader Spinner "M 0 100 a 100,100 0 0 1 100,-100 v 30 a 70,70 0 0 0 -70,70" -->
<Path Fill="Gold" Data="M 0 100 a 100,100 0 0 1 100,-100 v 30
a 70,70 0 0 0 -70,70" RenderTransformOrigin="1,1" >
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Canvas>
</Viewbox>
</UserControl>
字符串
对于Mimicing Marquee行为,我只需要绑定到<RotateTransform Angle="0"/>
即可(如果我没有弄错的话).然而,我被困在如何创建一个完整的进度条的一部分时,有一个情况下说,像成功连接到数据库和与字幕时,仍然试图连接.我怎么能做完整的进度条的一部分?如果有一个教程/视频,将解释如何做到这一点,我会很感激。
- 编辑1:* 我已经尝试了以下代码感谢@EldHasp在那里我做了以下事情:
SpinnerProgressBar.xaml
<UserControl x:Class="SpinnerProgress.SpinnerProgressBar"
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:SpinnerProgress"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
xmlns:rpb="clr-namespace:SpinnerProgress.spinnerprogressbar">
<!-- Spinner Design -->
<!-- Use the text document about the path commands in Data. -->
<Viewbox>
<Grid>
<!-- Arc Movement requirements: (Size, (RotatingAngle, isLargeArc, SweepDirection), Coordinates[End-points]) -->
<Canvas Width="100" Height="100">
<Path Stroke="LightGray" StrokeThickness="3" Fill="LightGray" Panel.ZIndex="2"
Data="M 0 100 a 100,100 0 1 1 200,0
a 100,100 0 1 1 -200,0
M 30 100 a 70,70 0 1 1 140,0
a 70,70 0 1 1 -140,0" RenderTransformOrigin="0.5,0.5" />
<!-- Arc Movement requirements: (Size, (RotatingAngle, isLargeArc, SweepDirection), Coordinates[End-points]) -->
<!-- Loader Spinner "M 0 100 a 100,100 0 0 1 100,-100 v 30 a 70,70 0 0 0 -70,70" -->
<Path x:Name="progressPath" Fill="Gold" RenderTransformOrigin="1,1">
<Path.Data>
<MultiBinding Converter="{x:Static local:ProgressBarToGeometryConverter.Instance}">
<Binding Path="Value" RelativeSource="{RelativeSource AncestorType=local:SpinnerProgressBar}"/>
<Binding Path="Maximum" RelativeSource="{RelativeSource AncestorType=local:SpinnerProgressBar}"/>
<Binding Path="Minimum" RelativeSource="{RelativeSource AncestorType=local:SpinnerProgressBar}"/>
</MultiBinding>
</Path.Data>
</Path>
</Canvas>
</Grid>
</Viewbox>
</UserControl>
型
SpinnerProgressBar背后的代码
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.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SpinnerProgress
{
/// <summary>
/// Interaction logic for SpinnerProgressBar.xaml
/// </summary>
public partial class SpinnerProgressBar : UserControl
{
public SpinnerProgressBar()
{
InitializeComponent();
}
private void StartMarqueeAnimation()
{
// Create a double animation to rotate the Path (marquee effect)
var rotationAnimation = new DoubleAnimation
{
To = 360, // Rotate a full circle (360 degrees)
Duration = TimeSpan.FromSeconds(1), // Adjust the duration as needed
RepeatBehavior = RepeatBehavior.Forever // Keep repeating the animation
};
progressPath.RenderTransform = new RotateTransform(); // Add a RotateTransform
progressPath.RenderTransformOrigin = new Point(1, 1); // Set the rotation origin to the center
// Begin the rotation animation
progressPath.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, rotationAnimation);
}
}
}
型
MainWindow.xaml
<Window x:Class="SpinnerProgress.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:SpinnerProgress"
xmlns:spb="clr-namespace:SpinnerProgress.spinnerprogressbar"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:5"
To="10"
Storyboard.TargetName="Spinner"
Storyboard.TargetProperty="Value"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid>
<spb:SpinnerProgressBar x:Name="Spinner" Maximum="10" Minimum="-10" Value="-10" Height="100" Width="100" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window>
型
Converter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media;
using static System.Math;
namespace SpinnerProgress.spinnerprogressbar
{
public class SpinnerProgressBar : RangeBase
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(SpinnerProgressBar), new PropertyMetadata(0.0));
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(SpinnerProgressBar), new PropertyMetadata(0.0));
public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(SpinnerProgressBar), new PropertyMetadata(0.0));
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public double Maximum
{
get { return (double)GetValue(MaximumProperty); }
set { SetValue(MaximumProperty, value); }
}
public double Minimum
{
get { return (double)GetValue(MinimumProperty); }
set { SetValue(MinimumProperty, value); }
}
static SpinnerProgressBar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SpinnerProgressBar), new FrameworkPropertyMetadata(typeof(SpinnerProgressBar)));
}
}
[ValueConversion(typeof(SpinnerProgressBar), typeof(Geometry))]
public class ProgressBarToGeometryConverter : IMultiValueConverter
{
private static readonly double valPI = 2 * PI;
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double min = (double)values[0];
double max = (double)values[1];
double value = (double)values[2];
double angle = (value - min) / (max - min);
angle *= valPI;
if (!double.IsNormal(angle))
return DependencyProperty.UnsetValue;
double cos = Cos(angle);
double sin = Sin(angle);
double x1 = 100 * cos + 100;
double y1 = 100 * sin + 100;
double x2 = 70 * cos + 100;
double y2 = 70 * sin + 100;
StreamGeometry sg = new();
sg.FillRule = FillRule.EvenOdd;
using StreamGeometryContext sgc = sg.Open();
if (value >= max)
{
sgc.BeginFigure(new Point(200, 100), true, true);
sgc.ArcTo(new Point(0, 100), new Size(100, 100), 0, false, SweepDirection.Clockwise, true, false);
sgc.ArcTo(new Point(200, 100), new Size(100, 100), 0, false, SweepDirection.Clockwise, true, false);
sgc.LineTo(new Point(170, 100), true, false);
sgc.ArcTo(new Point(30, 100), new Size(070, 070), 0, false, SweepDirection.Counterclockwise, true, false);
sgc.ArcTo(new Point(170, 100), new Size(070, 070), 0, false, SweepDirection.Counterclockwise, true, false);
}
else
if (angle < PI)
{
sgc.BeginFigure(new Point(200, 100), true, true);
sgc.ArcTo(new Point(x1, y1), new Size(100, 100), 0, false, SweepDirection.Clockwise, true, false);
sgc.LineTo(new Point(x2, y2), true, false);
sgc.ArcTo(new Point(170, 100), new Size(070, 070), 0, false, SweepDirection.Counterclockwise, true, false);
}
else
{
sgc.BeginFigure(new Point(200, 100), true, true);
sgc.ArcTo(new Point(x1, y1), new Size(100, 100), 0, true, SweepDirection.Clockwise, true, false);
sgc.LineTo(new Point(x2, y2), true, false);
sgc.ArcTo(new Point(170, 100), new Size(070, 070), 0, true, SweepDirection.Counterclockwise, true, false);
}
return sg;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public ProgressBarToGeometryConverter() { }
public static ProgressBarToGeometryConverter Instance { get; } = new();
}
[MarkupExtensionReturnType(typeof(ProgressBarToGeometryConverter))]
public class ProgressBarToGeometryExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return ProgressBarToGeometryConverter.Instance;
}
}
}
型
好像不行。我在想把字幕加到代码里。
2条答案
按热度按时间0s7z1bwu1#
圆形ProgressBar的示例。
自定义控件和转换器:
字符串
主题Generic.xaml:
型
窗口,其中包含Value属性的使用示例和动画:
型
Value属性可以绑定到ViewModel或以任何其他方式设置。进度将正确显示。
**P.S.**这是使用StreamGeometry的转换器的改进版本。
型
“编辑1”错误
1.“class SpinnerProgressBar:UserControl”-这个类是多余的。删除它。
1.在类“class SpinnerProgressBar:RangeBase”中,不需要声明Minimum、Maxmimum和Value属性。这些属性已经在基类“RangeBase”中声明。
1.类“SpinnerProgressBar:RangeBase”是一个自定义控件,您需要为其声明一个主题。默认主题是文件“Themes/Generic.xaml”。
您可以从这里下载完整的工作项目:https://drive.google.com/file/d/1lUpKDHz0QQ_NoFEXeXeWBcBMVgj8WZhW/view?usp=drive_link
ddrv8njm2#
为 Marquee 效果制作旋转动画非常简单,只需要设置
RenderTransform.RotateTranform
属性的动画。下面是
Storyboard
的声明,带有一些额外的旋转效果,以及IsMouseOver
在选定Path
上触发的示例。字符串
但是为了创建一个完整的进度条,这是一个更复杂的任务。
首先,你需要控制创建的
Storyboards
,即停止和启动他们需要时。也为ProgressBar
本身,我建议从ProgressBar
控件派生和风格,如你所愿。首先创建一个 * 标准 * 的
ProgressBar
,但基于来自MSDN https://learn.microsoft.com/en-us/dotnet/desktop/wpf/controls/progressbar-styles-and-templates?view=netframeworkdesktop-4.8的示例进行样式化,这是一个好的开始