我已经调整了一些我在网上找到的循环进度条的代码,它可以工作,直到进度条达到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" />
这是样式和转换器
<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>
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();
}
}
}
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;
}
}
}
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();
}
}
}
StartPointConverter.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;
}
}
}
答案 0 :(得分:4)
我有一个非常快速的解决方法,你不需要改变任何东西,但它仍然是一种解决方法;)
在您的ArcEndPointConverter
中添加此行
if (degrees == 360) degrees = 359.99;
在转换为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);
...