Я пытаюсь адаптировать пирог ProgressBar, найденный в книге WPF 4 Unleashed, чтобы выглядеть пончиком. Я чувствую, что я на полпути, но я не знаю, как решить последнюю проблему.WPF Donut ProgressBar
Вот картина, иллюстрирующая то, что я хочу и что мне удалось достичь:
- Это, как я хочу, чтобы она выглядела.
- Это то, на что похоже, используя приведенный ниже код.
- Я нашел предложение в другом вопросе здесь, в stackoverflow, который должен был использовать отсечение на пути и удвоить толщину штриха. Поскольку вы можете видеть, что путь позиционируется правильно, но любой прогресс ниже 50% не отображается правильно, как вы можете видеть.
Так что мой вопрос в том, как я могу исправить это так, как будто хочу?
Ниже приведен соответствующий XAML, я использую:
<ControlTemplate x:Key="DonutProgressBar" TargetType="{x:Type ProgressBar}">
<ControlTemplate.Resources>
<conv:ValueMinMaxToIsLargeArcConverter x:Key="ValueMinMaxToIsLargeArcConverter" />
<conv:ValueMinMaxToPointConverter x:Key="ValueMinMaxToPointConverter" />
</ControlTemplate.Resources>
<Grid>
<Viewbox>
<Grid Width="20" Height="20">
<Ellipse x:Name="Background"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness.Top}"
Width="20"
Height="20"
Fill="{TemplateBinding Background}" />
<Path x:Name="Donut"
Stroke="{TemplateBinding Foreground}"
StrokeThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness.Top}">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="10,0">
<ArcSegment Size="10,10" SweepDirection="Clockwise">
<ArcSegment.Point>
<MultiBinding Converter="{StaticResource ValueMinMaxToPointConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
</MultiBinding>
</ArcSegment.Point>
<ArcSegment.IsLargeArc>
<MultiBinding Converter="{StaticResource ValueMinMaxToIsLargeArcConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum" />
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum" />
</MultiBinding>
</ArcSegment.IsLargeArc>
</ArcSegment>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Grid>
</Viewbox>
</Grid>
</ControlTemplate>
...
<ProgressBar Width="70" Height="70" Value="40" Template="{StaticResource DonutProgressBar}" Background="{x:Null}" BorderBrush="#1F000000" BorderThickness="6,6,1,1" />
... и преобразователи:
public class ValueMinMaxToPointConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double value = (double)values[0];
double minimum = (double)values[1];
double maximum = (double)values[2];
double current = (value/(maximum - minimum)) * 360;
if (current == 360)
current = 359.999;
current = current - 90;
current = current * (Math.PI/180.0);
double x = 10 + 10 * Math.Cos(current);
double y = 10 + 10 * Math.Sin(current);
return new Point(x, y);
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
public class ValueMinMaxToIsLargeArcConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
double value = (double)values[0];
double minimum = (double)values[1];
double maximum = (double)values[2];
return ((value * 2) >= (maximum - minimum));
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Спасибо, мне удалось заставить его работать с вашими предложениями и пересчитанным радиусом. – dbostream