WPF和Winform都为我们提供了ProgressBar进度条。但是这种死板的进度条已经不能满足用户对美的要求了。因此,本篇文章要为大家展示一种圆形进度条。
为了方便进度条的复用,我们将进度条制作成用户控件。
<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>
#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
<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>
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等待画面!
本篇文章是设置好圆的透明度,随着时间的推移修改每个圆的位置实现转动。分享的文章是设置好每个圆的位置,改变圆的透明度,实现了假象的转动。