WPF进度条渲染

发布于:2025-02-13 ⋅ 阅读:(10) ⋅ 点赞:(0)

Xaml中:

 <Window.Resources>
     <local:BorderClipConverter x:Key="BorderClipConverter" />
     <Style x:Key="BorderClip" TargetType="{x:Type Border}">
         <Setter Property="UIElement.Clip">
             <Setter.Value>
                 <MultiBinding Converter="{StaticResource BorderClipConverter}">
                     <Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}" />
                     <Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}" />
                     <Binding Path="CornerRadius" RelativeSource="{RelativeSource Self}" />
                 </MultiBinding>
             </Setter.Value>
         </Setter>
     </Style>
 </Window.Resources>
 <Grid>
     <ProgressBar
         Width="570"
         Height="28"
         Margin="0,68,0,0"
         Value="100">
         <ProgressBar.Resources>
             <Style TargetType="ProgressBar">
                 <Setter Property="BorderThickness" Value="0" />
                 <Setter Property="Template">
                     <Setter.Value>
                         <ControlTemplate TargetType="{x:Type ProgressBar}">
                             <Border
                                 Name="TemplateRoot"
                                 Background="{TemplateBinding Background}"
                                 BorderBrush="{TemplateBinding BorderBrush}"
                                 BorderThickness="{TemplateBinding BorderThickness}"
                                 CornerRadius="20">
                                 <Grid>
                                     <Rectangle Name="PART_Track" />
                                     <Border
                                         Name="PART_Indicator"
                                         HorizontalAlignment="Left"
                                         Background="#ECECEC"
                                         CornerRadius="20"
                                         Style="{StaticResource BorderClip}">
                                         <Grid>
                                             <Rectangle
                                                 Name="PART_GlowRect"
                                                 Width="100"
                                                 HorizontalAlignment="Left"
                                                 Fill="#19BE6B"
                                                 RadiusX="20"
                                                 RadiusY="20" />
                                             <Rectangle
                                                 Name="Animation"
                                                 Fill="{TemplateBinding Foreground}"
                                                 RenderTransformOrigin="0.5,0.5"
                                                 Visibility="Collapsed">
                                                 <Rectangle.RenderTransform>
                                                     <TransformGroup>
                                                         <ScaleTransform />
                                                     </TransformGroup>
                                                 </Rectangle.RenderTransform>
                                             </Rectangle>
                                         </Grid>
                                     </Border>
                                 </Grid>
                             </Border>
                         </ControlTemplate>
                     </Setter.Value>
                 </Setter>
             </Style>
         </ProgressBar.Resources>
     </ProgressBar>
     <Button
         Height="28"
         Click="Button_Click"
         Content="进度条百分" />


     <ProgressBar
         Name="progressBar1"
         Width="570"
         Height="28"
         Margin="0,200,0,0" >
         <ProgressBar.Resources>
             <Style TargetType="{x:Type ProgressBar}">
                 <Setter Property="Background" Value="#19BE6B" />
                 <Setter Property="FontSize" Value="30" />
                 <Setter Property="Padding" Value="5,0" />
                 <Setter Property="Template">
                     <Setter.Value>
                         <ControlTemplate TargetType="{x:Type ProgressBar}">
                             
                             <Grid>
                                 <Border
                                     Background="#ECECEC"
                                     BorderThickness="0"
                                     CornerRadius="20" />
                                 <Grid Margin="{TemplateBinding BorderThickness}">
                                     <Rectangle x:Name="PART_Track" />
                                     <Border
                                         x:Name="PART_Indicator"
                                         HorizontalAlignment="Left"
                                         ClipToBounds="True"
                                         Style="{StaticResource BorderClip}">

                                         <Grid  RenderTransformOrigin="0.5,0.5">
                                             <Grid.RenderTransform>
                                                 <TransformGroup>
                                                     <ScaleTransform ScaleX="1" ScaleY="-1" />
                                                     <SkewTransform AngleX="0" AngleY="0" />
                                                     <RotateTransform Angle="180" />
                                                     <TranslateTransform />
                                                 </TransformGroup>
                                             </Grid.RenderTransform>
                                             <Border Background="{TemplateBinding Background}" CornerRadius="20">
                                                 <Viewbox
                                                     Margin="{TemplateBinding Padding}"
                                                     HorizontalAlignment="Left"
                                                     SnapsToDevicePixels="True"
                                                     StretchDirection="DownOnly">
                                                     <TextBlock
                                                         VerticalAlignment="Center"
                                                         FontSize="{TemplateBinding FontSize}"
                                                         Foreground="#ffffff"
                                                         RenderTransformOrigin="0.5,0.5"
                                                         SnapsToDevicePixels="True"
                                                         Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Value, StringFormat={}{0}%}">
                                                         <TextBlock.RenderTransform>
                                                             <TransformGroup>
                                                                 <ScaleTransform ScaleX="-1" ScaleY="1" />
                                                                 <SkewTransform AngleX="0" AngleY="0" />
                                                                 <RotateTransform Angle="0" />
                                                                 <TranslateTransform />
                                                             </TransformGroup>
                                                         </TextBlock.RenderTransform>
                                                     </TextBlock>
                                                 </Viewbox>
                                             </Border>
                                             <Border
                                                 BorderBrush="#000000"
                                                 BorderThickness="1"
                                                 CornerRadius="20"
                                                 Opacity="0.1" />
                                         </Grid>

                                     </Border>
                                 </Grid>
                             </Grid>
                            

                         </ControlTemplate>
                     </Setter.Value>
                 </Setter>
             </Style>
         </ProgressBar.Resources>
     </ProgressBar>
 </Grid>

CS中:

public class BorderClipConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length == 3)
        {
            object obj = values[0];
            if (obj is double)
            {
                double num = (double)obj;
                obj = values[1];
                if (obj is double)
                {
                    double num2 = (double)obj;
                    obj = values[2];
                    if (obj is CornerRadius)
                    {
                        CornerRadius cornerRadius = (CornerRadius)obj;
                        if (num < double.Epsilon || num2 < double.Epsilon)
                        {
                            return Geometry.Empty;
                        }

                        PathGeometry pathGeometry = new PathGeometry();
                        pathGeometry.Figures = new PathFigureCollection
                        {
                            new PathFigure(new Point(cornerRadius.TopLeft, 0.0), new PathSegment[8]
                            {
                                new LineSegment(new Point(num - cornerRadius.TopRight, 0.0), isStroked: false),
                                new ArcSegment(new Point(num, cornerRadius.TopRight), new Size(cornerRadius.TopRight, cornerRadius.TopRight), 90.0, isLargeArc: false, SweepDirection.Clockwise, isStroked: false),
                                new LineSegment(new Point(num, num2 - cornerRadius.BottomRight), isStroked: false),
                                new ArcSegment(new Point(num - cornerRadius.BottomRight, num2), new Size(cornerRadius.BottomRight, cornerRadius.BottomRight), 90.0, isLargeArc: false, SweepDirection.Clockwise, isStroked: false),
                                new LineSegment(new Point(cornerRadius.BottomLeft, num2), isStroked: false),
                                new ArcSegment(new Point(0.0, num2 - cornerRadius.BottomLeft), new Size(cornerRadius.BottomLeft, cornerRadius.BottomLeft), 90.0, isLargeArc: false, SweepDirection.Clockwise, isStroked: false),
                                new LineSegment(new Point(0.0, cornerRadius.TopLeft), isStroked: false),
                                new ArcSegment(new Point(cornerRadius.TopLeft, 0.0), new Size(cornerRadius.TopLeft, cornerRadius.TopLeft), 90.0, isLargeArc: false, SweepDirection.Clockwise, isStroked: false)
                            }, closed: false)
                        };
                        pathGeometry.Freeze();
                        return pathGeometry;
                    }
                }
            }
        }

        return DependencyProperty.UnsetValue;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

事件方法

private void Button_Click(object sender, RoutedEventArgs e)
{
    //测试代码
    Thread thread = new Thread(new ThreadStart(() =>
    {
        for (int i = 0; i <= 100; i++)
        {
            this.progressBar1.Dispatcher.BeginInvoke((ThreadStart)delegate { this.progressBar1.Value = i; });
            Thread.Sleep(300);
        }
    }));
    thread.Start();
    //测试代码
}