WPF和Winform都为我们提供了ProgressBar进度条。但是这种死板的进度条已经不能满足用户对美的要求了。因此,本篇文章要为大家展示一种圆形进度条。
为了方便进度条的复用,我们将进度条制作成用户控件。
代码展示:
圆形进度条用户控件的制作:
LoadingWait.xaml
<UserControl x:Class="进度条.LoadingWait"
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" Background="#19A39E9E" Name="loadingWait">
<!--设置圆的颜色-->
<UserControl.Resources>
<SolidColorBrush Color="CornflowerBlue" x:Key="CirclesColor"/>
</UserControl.Resources>
<Grid>
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center">
<Viewbox Width="100" Height="100"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Grid x:Name="LayoutRoot"
Background="Transparent"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<!--此处有canvas的加载和卸载事件-->
<Canvas RenderTransformOrigin="0.5,0.5"
HorizontalAlignment="Center"
VerticalAlignment="Center" Width="120"
Height="120" Loaded="HandleLoaded"
Unloaded="HandleUnloaded" >
<!--画圆,设置成不同的透明度Opacity-->
<Ellipse x:Name="C0" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="1.0"/>
<Ellipse x:Name="C1" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.9"/>
<Ellipse x:Name="C2" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.8"/>
<Ellipse x:Name="C3" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.7"/>
<Ellipse x:Name="C4" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.6"/>
<Ellipse x:Name="C5" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.5"/>
<Ellipse x:Name="C6" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.4"/>
<Ellipse x:Name="C7" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.3"/>
<Ellipse x:Name="C8" Width="20" Height="20"
Canvas.Left="0"
Canvas.Top="0" Stretch="Fill"
Fill="{StaticResource CirclesColor}" Opacity="0.2"/>
<Canvas.RenderTransform>
<RotateTransform x:Name="SpinnerRotate"
Angle="0" />
</Canvas.RenderTransform>
</Canvas>
</Grid>
</Viewbox>
<!--这两个针对的元素名称是loadingWait,所以必须要给本界面一个名称-->
<!--TextBlock里面放置提示信息;Label放置相当于按钮的东西-->
<TextBlock Text="{Binding TipContent,ElementName=loadingWait}" FontStretch="Medium" HorizontalAlignment="Center" FontSize="16"></TextBlock>
<Label Content="{Binding InnerContent,ElementName=loadingWait}" HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
</UserControl>
LoadingWait.xaml.cs
#region 参数
// 集成到按指定时间间隔和指定优先级处理的 System.Windows.Threading.Dispatcher 队列中的计时器。
private readonly DispatcherTimer animationTimer;
#endregion
#region 构造方法
/// <summary>
/// 构造方法
/// </summary>
public LoadingWait()
{
InitializeComponent();
animationTimer = new DispatcherTimer(DispatcherPriority.ContextIdle, Dispatcher);
animationTimer.Interval = new TimeSpan(0, 0, 0, 0, 75); //指定时间间隔
}
#endregion
#region 属性
#region 得到要显示的提示信息
/// <summary>
/// 得到要显示的提示信息
/// </summary>
public string TipContent
{
get { return (string)GetValue(TipContentProperty); }
set { SetValue(TipContentProperty, value); }
}
public static readonly DependencyProperty TipContentProperty = DependencyProperty.Register("TipContent", typeof(string), typeof(LoadingWait), new UIPropertyMetadata("正在处理..."));
#endregion
#region 按钮的名称--例如:取消
/// <summary>
/// 按钮的名称
/// </summary>
public object InnerContent
{
get { return (object)GetValue(InnerContentProperty); }
set { SetValue(InnerContentProperty, value); }
}
// Using a DependencyProperty as the backing store for InnerContent. This enables animation, styling, binding, etc...
public static readonly DependencyProperty InnerContentProperty =
DependencyProperty.Register("InnerContent", typeof(object), typeof(LoadingWait), new UIPropertyMetadata(null));
#endregion
#region 按钮的显示或隐藏
/// <summary>
/// 按钮的显示与隐藏
/// </summary>
public Visibility InnerContentVisibility
{
get { return (Visibility)GetValue(InnerContentVisibilityProperty); }
set { SetValue(InnerContentVisibilityProperty, value); }
}
// Using a DependencyProperty as the backing store for InnerContentVisibility. This enables animation, styling, binding, etc...
public static readonly DependencyProperty InnerContentVisibilityProperty =
DependencyProperty.Register("InnerContentVisibility", typeof(Visibility), typeof(LoadingWait), new UIPropertyMetadata(Visibility.Collapsed));
#endregion
#endregion
#region 方法
/// <summary>
/// 开始方法
/// </summary>
private void Start()
{
//修改光标的样式,为等待状态
this.Cursor = Cursors.Wait;
//超过计时器间隔时发生。
animationTimer.Tick += HandleAnimationTick;
animationTimer.Start();
}
/// <summary>
/// 结束方法
/// </summary>
private void Stop()
{
animationTimer.Stop();
//修改光标的样式,为箭头
this.Cursor = Cursors.Arrow;
animationTimer.Tick -= HandleAnimationTick;
}
/// <summary>
/// 超过计时器间隔时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HandleAnimationTick(object sender, EventArgs e)
{
//设置旋转角度
SpinnerRotate.Angle = (SpinnerRotate.Angle + 36) % 360;
}
/// <summary>
/// Canvas加载时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HandleLoaded(object sender, RoutedEventArgs e)
{
//圆周长就是:C = π * d 或者C=2*π*r(其中d是圆的直径,r是圆的半径)
const double offset = Math.PI; //π
const double step = Math.PI * 2 / 10.0;
SetPositin(C0, offset, 0.0, step);
SetPositin(C1, offset, 1.0, step);
SetPositin(C2, offset, 2.0, step);
SetPositin(C3, offset, 3.0, step);
SetPositin(C4, offset, 4.0, step);
SetPositin(C5, offset, 5.0, step);
SetPositin(C6, offset, 6.0, step);
SetPositin(C7, offset, 7.0, step);
SetPositin(C8, offset, 8.0, step);
this.IsVisibleChanged -= HandleVisibleChanged;
this.IsVisibleChanged += HandleVisibleChanged;
DesignerProperties 提供用于与设计器进行通信的附加属性。
if (!DesignerProperties.GetIsInDesignMode(this))
{
if (this.Visibility == System.Windows.Visibility.Visible)
{
Start();
}
}
}
/// <summary>
/// Canvas卸载时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HandleUnloaded(object sender, RoutedEventArgs e)
{
Stop();
}
/// <summary>
/// 确定圆的位置
/// </summary>
/// <param name="ellipse"></param>
/// <param name="offset"></param>
/// <param name="posOffSet"></param>
/// <param name="step"></param>
private void SetPositin(Ellipse ellipse, double offset, double posOffSet, double step)
{
ellipse.SetValue(Canvas.LeftProperty, 50.0 + Math.Sin(offset + posOffSet * step) * 50.0);
ellipse.SetValue(Canvas.TopProperty, 50 + Math.Cos(offset + posOffSet * step) * 50.0);
}
/// <summary>
/// 设置显示与隐藏
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void HandleVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
bool isVisible = (bool)e.NewValue;
if (isVisible)
Start();
else
Stop();
}
#endregion
Window界面使用圆形进度条用户控件:
Window.xaml
<pre name="code" class="csharp"><Grid>
<Grid.RowDefinitions>
<RowDefinition Height="42*" />
<RowDefinition Height="219*" />
</Grid.RowDefinitions>
<Button Content="开始" Height="23" HorizontalAlignment="Left" Margin="39,12,0,0" Name="btnBegin" VerticalAlignment="Top" Width="75" Click="btnBegin_Click" />
<Button Content="结束" Height="23" HorizontalAlignment="Left" Margin="162,12,0,0" Name="btnEnd" VerticalAlignment="Top" Width="75" Click="btnEnd_Click" />
<!--TipContent:绑定要显示的提示信息-->
<my:LoadingWait Visibility="Collapsed" TipContent="正在处理..." x:Name="loadingWait" Grid.Row="2">
<my:LoadingWait.InnerContent>
<StackPanel>
<!--这些事件也可以使用绑定来完成,例如:Command="{Binding FXBCXNoCmd}"-->
<Button Content="取消" Width="300" Click="Button_Click"></Button>
</StackPanel>
</my:LoadingWait.InnerContent>
</my:LoadingWait>
</Grid>
Window.xaml.cs
private void btnBegin_Click(object sender, RoutedEventArgs e)
{
loadingWait.Visibility = Visibility.Visible;
loadingWait.TipContent = "处理中。。。";
}
private void btnEnd_Click(object sender, RoutedEventArgs e)
{
loadingWait.Visibility = Visibility.Collapsed;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//此处可以写取消事件
loadingWait.TipContent = "正在取消...";
loadingWait.Visibility = Visibility.Collapsed;
}
以上事件也可以使用绑定来完成,参考:wpf之mvvm。
效果图:
小编曾看到另一种制作圆形进度条的方法,感觉不错,分享给大家--WPF 圆形Loading等待画面!
本篇文章是设置好圆的透明度,随着时间的推移修改每个圆的位置实现转动。分享的文章是设置好每个圆的位置,改变圆的透明度,实现了假象的转动。