本文主要讲我设计的几个进度条,还有如何使用异步控制进度条,如何使用动画做进度。
进度条可以参见:
进度条其实异步就是使用后台变化,然后 value 绑定
我使用一个
需要设置他的各个值,如果不设置,一般最大值为 100,最小为 0,所以可以表示百分数,其中 Value 是 double,绑定后台就好。
- ProgressBar
"`
- <ProgressBar Maximum="100" Value="{x:Bind View.Value,Mode=OneWay}" Height="20"
- Width="100">
- </ProgressBar>
- 绑定到我们的ViewModel,一般如果后台线程操作界面是不能直接,但是我用了```await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () = >{});
代码参见:,项目所有代码都会发出
我们使用 Task 异步,我们因为没有什么耗时的,就
我们进度会等一秒,当然自己也可以设置多些。也可以写
- Task.Delay(1000).Wait();
- await Task.Dalay(1000);
ViewModel
- public ViewModel() {
- new Task(() = >{
- while (Value < 90) {
- Value += 10;
- Task.Delay(1000).Wait();
- }
- }).Start();
- }
- public double Value {
- set {
- _value = value;
- OnPropertyChanged();
- }
- get {
- return _value;
- }
- }
- private double _value;
默认进度条设置最大值,
我还自己的控件,一个值从 0 到 100 的圆形的,可以看下面
## 圆形进度条
参见:
先说怎么用我的,首先去我源代码,打开我的进度条文件夹,里面有 View 文件夹
我在 View 有一个控件
复制他到你的解决方案,如果我的控件大小和你不一样,很简单调整,我就不说。
- RountProgress
那么我的控件只需要指定 Value 就好啦,Value 其实是从 0 到 100,如果叫别的应该好,但是我不改,如果你觉得不想要,自己改
- xmlns: view = "using:lindexi.uwp.control.RountProgress.View" < view: RountProgress Value = "{x:Bind Value,Mode=OneWay}" > </view:RountProgress>
- /
我来说下怎么做
我们要知道 StrokeDashArray,这个是一个数组,是循环的,也就是依此读取,知道超过长度。
首先我们需要有 Thickness,宽度,StrokeDashArray 的每一个都是宽度的倍数
首先取第一个元素,把这个元素乘以宽度,作为显示的大小,然后取第二个元素,乘以宽度,作为不显示的大小
然后循环获取第三个……,如果不存在第三个,那么循环拿第一做第三,n=n==max?0:n+1,n 就是第 n 个元素
一个显示一个不显示,循环
记得长度乘以是
- 值*宽度
那么我们如果有一个
的到大小比我们的宽度还大,那么就会截断。
- 值*宽度
假如我们宽度 3,StrokeDashArray 1,2,0.5,总长度为 5,那么
第一个是大小
显示,然后是
- 1*3
不显示,因为到第一个只有长度为 2,第二个大小为 6,所以会截断,3 显示然后 2 不显示
- 2*3
我们可以用第一个为一个值,然后第二个为一个比总长度还大的值,这样会让宽度显示为我们第一个的值,而其他为空,因为第二个比最大还大
我们要做一个
,我们需要算
- 30%
- 长=圆*30%/宽度
- 圆=PI*(总长度-宽度)
- <Ellipse x:Name="Rount" Stroke="DeepSkyBlue" Height="100" Width="100"
- StrokeThickness="3" RenderTransformOrigin="0.5,0.5" />
那么我们第一个值
- (总长度100 - 宽度3) \* PI / 宽度3
因为我们需要算我们的宽度不是直接总长度,是总长度 - 宽度
第二个最好是 Double.Max
我们想要一个可以用户进度,那么可以绑定一个属性,在我们控件
我们需要这个为
,然后绑定
- double
因为我们需要两个值,所以转换
假如我们的转换是固定的总长度,宽度,那么可以使用
- public object Convert(object value, Type targetType, object parameter, string language) {
- double thine = 3;
- double w = 100 - thine;
- double n = Math.PI * w / thine * (double) value / 100;
- DoubleCollection temp = new DoubleCollection() {
- n,
- 1000
- };
- return temp;
- }
如果觉得固定不好,可以在我们转换写属性,然后在界面把我们的宽度给属性,然后换为我们的宽度算,这个简单
代码在
那么进度条如果不需要进度,那么我有一些好的,例如我之前的博客有说的,还有一个简单,也是上面改,我们一个值是显示一个值是不显示,那么我们可以做
- "lindexi.uwp.control.RountProgress.View.IndeterminateProgress"xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns: x = "http://schemas.microsoft.com/winfx/2006/xaml"xmlns: local = "using:lindexi.uwp.control.RountProgress.View"xmlns: d = "http://schemas.microsoft.com/expression/blend/2008"xmlns: mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"mc: Ignorable = "d"d: DesignHeight = "300"d: DesignWidth = "400" >
- <Style TargetType = "ProgressRing" > <Setter Property = "Background"Value = "Transparent" / ><Setter Property = "Foreground"Value = "{ThemeResource SystemControlHighlightAccentBrush}" / ><Setter Property = "IsHitTestVisible"Value = "False" / ><Setter Property = "HorizontalAlignment"Value = "Center" / ><Setter Property = "VerticalAlignment"Value = "Center" / ><Setter Property = "MinHeight"Value = "20" / ><Setter Property = "MinWidth"Value = "20" / ><Setter Property = "IsTabStop"Value = "False" / ><Setter Property = "Template" > <Setter.Value > "ProgressRing" > <Grid x: Name = "Ring"BorderBrush = "{TemplateBinding BorderBrush}"BorderThickness = "{TemplateBinding BorderThickness}"Background = "{TemplateBinding Background}"FlowDirection = "LeftToRight"MaxWidth = "{Binding TemplateSettings.MaxSideLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"MaxHeight = "{Binding TemplateSettings.MaxSideLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"Padding = "{TemplateBinding Padding}"RenderTransformOrigin = ".5,.5" > <Grid.Resources > <Style x: Key = "ProgressRingEllipseStyle"TargetType = "Ellipse" > <Setter Property = "Opacity"Value = "0" / ><Setter Property = "HorizontalAlignment"Value = "Left" / ><Setter Property = "VerticalAlignment"Value = "Top" / ></Style>
- </Grid.Resources > "SizeStates" > "Large" >
- "Small" / >
- "ActiveStates" > "Inactive" / >"Active" > "Forever" > "Rount"Storyboard.TargetProperty = "Angle"BeginTime = "0:0:0"Duration = "0:0:5"From = "0"To = "360" >
- "DeepSkyBlue"Height = "100"Width = "100"StrokeThickness = "3"RenderTransformOrigin = "0.5,0.5" / >"DeepSkyBlue"Height = "200"Width = "200"StrokeThickness = "3"StrokeDashArray = "50 50"RenderTransformOrigin = "0.5,0.5" > "Rount"Angle = "0" / >
- </Grid>
- </Setter.Value > </Setter>
- </Style >
- <Grid > "200"Height = "200"IsActive = "True" > </Grid>
- /
我们使用一个简单的修改,因为我们可以使用
- <RotateTransform x:Name="Rount" Angle="0"/>
我们使用
- <VisualState x:Name="Active">
- <Storyboard RepeatBehavior="Forever">
- <DoubleAnimation Storyboard.TargetName="Rount" Storyboard.TargetProperty="Angle"
- Duration="0:0:5" From="0" To="360">
- </DoubleAnimation>
- </Storyboard>
- </VisualState>
修改我们旋转,时间 0:0:5,5 秒,从 0 到 360,循环
因为是修改,所以可以放在 Resource
- <ProgressRing Width="200" Height="200" IsActive="True">
- </ProgressRing>
我觉得匀速不好,修改速度
- ^2
- <Storyboard TargetName="Rount">
- <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" BeginTime="00:00:00"
- EnableDependentAnimation="True" Duration="0:0:2">
- <DiscreteObjectKeyFrame KeyTime="00:00:00">
- <DiscreteObjectKeyFrame.Value>
- <Thickness>
- 10,1,10,10
- </Thickness>
- </DiscreteObjectKeyFrame.Value>
- </DiscreteObjectKeyFrame>
- <DiscreteObjectKeyFrame KeyTime="00:00:02">
- <DiscreteObjectKeyFrame.Value>
- <Thickness>
- 10,200,10,10
- </Thickness>
- </DiscreteObjectKeyFrame.Value>
- </DiscreteObjectKeyFrame>
- </ObjectAnimationUsingKeyFrames>
- </Storyboard>
Rount 就是我们要修改的控件,我们看到这是在 2 就直接修改,没有从 1 到 200,这样其实并不是我们直接就想从 1 然后两秒 200
我们定义
- <local:IndeterminateProgress Margin="0,10,0,0" Width="200" Height="200">
- <local:IndeterminateProgress.RenderTransform>
- <TranslateTransform x:Name="Rount" Y="0">
- </TranslateTransform>
- </local:IndeterminateProgress.RenderTransform>
- </local:IndeterminateProgress>
- <DoubleAnimation Storyboard.TargetName="Rount" Storyboard.TargetProperty="Y"
- From="0" To="100" Duration="0:0:2">
- </DoubleAnimation>
我们要让我们的进度弹起来,如果不知道我说什么,简单我有图
其实我们要让我们的元素移动,可以看林政大神的书
- <local:IndeterminateProgress Margin="0,10,0,0" Width="200" Height="200">
- <local:IndeterminateProgress.RenderTransform>
- <TranslateTransform x:Name="Rount" Y="10" />
- </local:IndeterminateProgress.RenderTransform>
- </local:IndeterminateProgress>
在动画
- <DoubleAnimation Storyboard.TargetName="Rount" Storyboard.TargetProperty="Y"
- Duration="0:0:2" From="0" To="300">
- <DoubleAnimation.EasingFunction>
- <BounceEase Bounces="2">
- </BounceEase>
- </DoubleAnimation.EasingFunction>
- </DoubleAnimation>
我们使用 Rount,x,记得要给名字,然后两秒,从 0 到 300,下面就是弹跳,我上面有说,这个在官方有说比我写还好,但是官方的我没法拿来
来源: http://lib.csdn.net/article/csharp/45160