循环进度条问题

Mar*_*all 2 c# wpf

我已经修改了一些我在网上找到的圆形进度条的代码,它可以工作,直到进度条达到 100%,然后它就会消失......

我不知道出了什么问题,我假设这与 ArcSegment 的工作方式有关,但我不完全理解它背后的数学原理,有人能给我建议吗?

这是 ProgressBar 和 Slider:

<Slider Value="{Binding Source={StaticResource runtimeVariables}, Path=uploadProgress}" Maximum="100" Margin="0,0,252,0" />
        <ProgressBar Width="150" Style="{StaticResource CircularProgress}" Value="{Binding Source={StaticResource runtimeVariables},Path=uploadProgress}" Maximum="100" HorizontalAlignment="Left" />
Run Code Online (Sandbox Code Playgroud)

这是样式和转换器

<CircleProgress:StartPointConverter x:Key="StartPointConverter" />
    <CircleProgress:ArcSizeConverter x:Key="ArcSizeConverter" />
    <CircleProgress:ArcEndPointConverter x:Key="ArcEndPointConverter" />
    <CircleProgress:LargeArcConverter x:Key="LargeArcConverter" />
    <CircleProgress:SizeTextOnParent x:Key="SizeTextOnParent" />
    <CircleProgress:Difference x:Key="Difference" />

    <Style TargetType="ProgressBar" x:Key="CircularProgress">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ProgressBar">
                    <Grid x:Name="PathGrid" Width="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Width}">
                        <Canvas>
                            <DockPanel Height="{Binding ElementName=PathGrid, Path=Width}" Width="{Binding ElementName=PathGrid, Path=Width}">
                                <TextBlock x:Name="PathPercentage" 
                                           Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=Value, StringFormat={}{0}%}"
                                           Foreground="White"
                                           FontSize="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource SizeTextOnParent}}" 
                                           VerticalAlignment="Center" TextAlignment="Center">
                                </TextBlock>
                            </DockPanel>
                            <Path x:Name="pathRoot"
                                  Panel.ZIndex="1"
                                  Stroke="#8ab71c" 
                                  StrokeThickness="6" 
                                  HorizontalAlignment="Center" 
                                  VerticalAlignment="Top">
                                <Path.Data>
                                    <PathGeometry>
                                        <PathFigureCollection>
                                            <PathFigure StartPoint="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource StartPointConverter}, Mode=OneWay}">
                                                <ArcSegment Size="{Binding ElementName=PathGrid, Path=ActualWidth, Converter={StaticResource ArcSizeConverter}, Mode=OneWay}" SweepDirection="Clockwise">
                                                    <ArcSegment.IsLargeArc>
                                                        <MultiBinding Converter="{StaticResource LargeArcConverter}">
                                                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
                                                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
                                                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
                                                        </MultiBinding>
                                                    </ArcSegment.IsLargeArc>
                                                    <ArcSegment.Point>
                                                        <MultiBinding Converter="{StaticResource ArcEndPointConverter}">
                                                            <Binding ElementName="PathGrid" Path="ActualWidth" />
                                                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
                                                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
                                                            <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
                                                        </MultiBinding>
                                                    </ArcSegment.Point>
                                                </ArcSegment>
                                            </PathFigure>
                                        </PathFigureCollection>
                                    </PathGeometry>
                                </Path.Data>
                            </Path>
                            <Ellipse
                                x:Name="backCircle"
                                Panel.ZIndex="0"
                                Fill="Transparent"
                                Stroke="#434953" 
                                StrokeThickness="3" 
                                Width="{Binding ElementName=PathGrid, Path=Width}" 
                                Height="{Binding ElementName=PathGrid, Path=Width}" />
                        </Canvas>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
Run Code Online (Sandbox Code Playgroud)

ArcEndPointConverter.cs

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace Test_Project.Converters
{
    public class ArcEndPointConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var actualWidth = values[0].ExtractDouble();
            var value = values[1].ExtractDouble();
            var minimum = values[2].ExtractDouble();
            var maximum = values[3].ExtractDouble();

            if (new[] { actualWidth, value, minimum, maximum }.AnyNan())
                return Binding.DoNothing;

            if (values.Length == 5)
            {
                var fullIndeterminateScaling = values[4].ExtractDouble();
                if (!double.IsNaN(fullIndeterminateScaling) && fullIndeterminateScaling > 0.0)
                {
                    value = (maximum - minimum) * fullIndeterminateScaling;
                }
            }

            var percent = maximum <= minimum ? 1.0 : (value - minimum) / (maximum - minimum);
            var degrees = 360 * percent;
            var radians = degrees * (Math.PI / 180);

            var centre = new Point(actualWidth / 2, actualWidth / 2);
            var hypotenuseRadius = (actualWidth / 2);

            var adjacent = Math.Cos(radians) * hypotenuseRadius;
            var opposite = Math.Sin(radians) * hypotenuseRadius;

            return new Point(centre.X + opposite, centre.Y - adjacent);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ArcSizeConverter.cs

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace Test_Project.Converters
{
    public class ArcSizeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is double && ((double)value > 0.0))
            {
                return new Size((double)value / 2, (double)value / 2);
            }

            return new Point();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

LargeArcConverter.cs

using System;
using System.Globalization;
using System.Windows.Data;

namespace Test_Project.Converters
{
    public class LargeArcConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var value = values[0].ExtractDouble();
            var minimum = values[1].ExtractDouble();
            var maximum = values[2].ExtractDouble();

            if (new[] { value, minimum, maximum }.AnyNan())
                return Binding.DoNothing;

            if (values.Length == 4)
            {
                var fullIndeterminateScaling = values[3].ExtractDouble();
                if (!double.IsNaN(fullIndeterminateScaling) && fullIndeterminateScaling > 0.0)
                {
                    value = (maximum - minimum) * fullIndeterminateScaling;
                }
            }

            var percent = maximum <= minimum ? 1.0 : (value - minimum) / (maximum - minimum);

            return percent > 0.5;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

起点转换器.cs

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace Test_Project.Converters
{
    public class StartPointConverter : IValueConverter
    {
        [Obsolete]
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is double && ((double)value > 0.0))
            {
                return new Point((double)value / 2, 0);
            }

            return new Point();
        }

        [Obsolete]
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

kir*_*tab 5

我为您提供了一个非常快速的解决方法,您无需更改任何内容,但它仍然是一种解决方法;)

在你ArcEndPointConverter刚刚添加这一行

if (degrees == 360) degrees = 359.99;
Run Code Online (Sandbox Code Playgroud)

在转换为 Radians 之前,我认为否则该值等于您的最终度数为 0° 时的值,因此我们只是将其欺骗为几乎 360°,以便它可以自行绘制(通过我的测试,人眼不可见)

...
var percent = maximum <= minimum ? 1.0 : (value - minimum) / (maximum - minimum);
var degrees = 360 * percent;
if (degrees == 360) degrees = 359.99;
var radians = degrees * (Math.PI / 180);
...
Run Code Online (Sandbox Code Playgroud)