英文:
How to create Custom progress bar minimum value 0 starts from the bottom left corner?
问题
我想要将进度条的起始点设为0%,结束点设为100%,并放置在左下角。并且希望数值的变化能够正常显示。我该如何实现?
我希望进度条的数值在圆形上增加和减少。
我的测试结果不正确,我不知道问题出在哪里以及如何解决它。
Xaml:
<!-- 代码省略 -->
Codebehind:
// 代码省略
结果:
编辑:
更新:
我如何通过拖动球来改变进度值?
<!-- 代码省略 -->
英文:
I want the starting point 0% and the ending point 100% of the progress bar to be in the lower left corner. And the progress of the value changes to display normally. How can I accomplish it?
I want the progress bar to increase and decrease in value along the circle.
The result of my test is not correct, I don't know where is the problem and how to fix it.
Xaml:
<Window.Resources>
<local:AngleToPointConverter x:Key="prConverter"/>
<local:AngleToIsLargeConverter x:Key="isLargeConverter"/>
<Style x:Key="circularProgressBar" TargetType="local:CircularProgressBar">
<Setter Property="Value" Value="10"/>
<Setter Property="Maximum" Value="100"/>
<Setter Property="StrokeThickness" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CircularProgressBar">
<Canvas Width="100" Height="130">
<Ellipse Width="101" Height="101" Stroke="LightGray" Opacity="0.7" StrokeThickness="4" />
<Path Stroke="{TemplateBinding Background}"
StrokeThickness="{TemplateBinding StrokeThickness}">
<Path.Data>
<PathGeometry>
<PathFigure x:Name="fig" StartPoint="20,90">
<ArcSegment RotationAngle="0" SweepDirection="Clockwise"
Size="50,50"
Point="{Binding Path=Angle, Converter={StaticResource prConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
IsLargeArc="{Binding Path=Angle, Converter={StaticResource isLargeConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
>
</ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Border Width="100" Height="100">
<Grid>
<Ellipse Width="50" Height="50" Fill="White" />
<Image Width="20" Height="20" Margin="30,25,30,30" Source="bulb1.PNG"/>
<TextBlock Width="50" Foreground="Black" Height="20" Margin="10,40,10,5" TextAlignment="Center"
Text="{Binding Path=Value, StringFormat={}{0}%,
RelativeSource={RelativeSource TemplatedParent}}"
FontSize="{TemplateBinding FontSize}"/>
</Grid>
</Border>
<Canvas Canvas.Top="110">
<Button x:Name="decrease" Margin="20,0,0,0" Command="{Binding DecreaseCommand}" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" />
<Border Width="20" Height="20" >
<TextBlock Foreground="LightGray" Text="-" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Button x:Name="increase" Margin="60,0,0,0" Grid.Column="1" Command="{Binding IncreaseCommand}" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" />
<Border Width="20" Height="20" Grid.Column="1">
<TextBlock Foreground="LightGray" Text="+" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<!--<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" Margin="20,0,0,0"/>
<Border Width="20" Height="20" Margin="20,0,0,0">
<TextBlock Foreground="LightGray" Text="-" HorizontalAlignment="Center" />
</Border>
<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" Margin="60,0,0,0"/>
<Border Width="20" Height="20" Margin="60,0,0,0">
<TextBlock Foreground="LightGray" Text="+" HorizontalAlignment="Center" />
</Border>-->
</Canvas>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="DarkBlue">
<local:CircularProgressBar Background="White" Style="{StaticResource circularProgressBar }"
Value="{Binding ElementName=CirularSlider, Path= Value}" Foreground="Black" FontWeight="Bold"
StrokeThickness="4"
BorderBrush="LightGray"/>
<Slider Minimum="0" Maximum="100"
x:Name="CirularSlider" IsSnapToTickEnabled="True"
VerticalAlignment="Top" Value="10"/>
</Grid>
Codebedhind:
public class CircularProgressBar : ProgressBar
{
public CircularProgressBar()
{
this.ValueChanged += CircularProgressBar_ValueChanged;
}
void CircularProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
CircularProgressBar bar = sender as CircularProgressBar;
double currentAngle = bar.Angle;
double targetAngle = e.NewValue / bar.Maximum * 359.999;
// double targetAngle = e.NewValue / bar.Maximum * 179.999;
DoubleAnimation anim = new DoubleAnimation(currentAngle, targetAngle, TimeSpan.FromMilliseconds(500));
bar.BeginAnimation(CircularProgressBar.AngleProperty, anim, HandoffBehavior.SnapshotAndReplace);
}
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
// Using a DependencyProperty as the backing store for Angle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(CircularProgressBar), new PropertyMetadata(0.0));
public double StrokeThickness
{
get { return (double)GetValue(StrokeThicknessProperty); }
set { SetValue(StrokeThicknessProperty, value); }
}
// Using a DependencyProperty as the backing store for StrokeThickness. This enables animation, styling, binding, etc...
public static readonly DependencyProperty StrokeThicknessProperty =
DependencyProperty.Register("StrokeThickness", typeof(double), typeof(CircularProgressBar), new PropertyMetadata(10.0));
}
public class AngleToPointConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double angle = (double)value;
double radius = 50;
double piang = angle * Math.PI / 180;
//double piang = angle * Math.PI / 310;
double px = Math.Sin(piang) * radius + radius;
double py = -Math.Cos(piang) * radius + radius;
return new System.Windows.Point(px, py);
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class AngleToIsLargeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double angle = (double)value;
return angle > 180;
// return angle > 300;
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Edit:
Update:
How can I change the progress value by dragging the ball?
<Style x:Key="circularProgressBar1" TargetType="local:CircularProgressBar">
<Setter Property="Value" Value="10"/>
<Setter Property="Maximum" Value="100"/>
<Setter Property="StrokeThickness" Value="7"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:CircularProgressBar">
<Canvas Width="100" Height="130">
<Ellipse Width="105" Height="104" Margin="-2.4,-1.5,0,0" Stroke="LightGray" Opacity="0.7" StrokeThickness="8" />
<Path Stroke="{TemplateBinding Background}" StrokeStartLineCap="Round" StrokeEndLineCap="Round"
StrokeThickness="{TemplateBinding StrokeThickness}">
<Path.Data>
<PathGeometry>
<PathFigure x:Name="fig" StartPoint="20,90">
<ArcSegment RotationAngle="0" SweepDirection="Clockwise"
Size="50,50"
Point="{Binding Path=Angle, Converter={StaticResource prConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
IsLargeArc="{Binding Path=Angle, Converter={StaticResource isLargeConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}"
>
</ArcSegment>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
<Button>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Path Stroke="Black" StrokeThickness="10" StrokeStartLineCap="Round" StrokeEndLineCap="Round">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="{Binding Path=Angle, Converter={StaticResource prConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}">
<PathFigure.Segments>
<LineSegment Point="{Binding Path=Angle, Converter={StaticResource prConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType=ProgressBar}}" />
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Border Width="100" Height="100">
<Grid>
<Ellipse Width="50" Height="50" Fill="White" />
<Image Width="20" Height="20" Margin="30,25,30,30" Source="bulb1.PNG"/>
<TextBlock Width="50" Foreground="Black" Height="20" Margin="10,40,10,5" TextAlignment="Center"
Text="{Binding Path=Value, StringFormat={}{0}%,
RelativeSource={RelativeSource TemplatedParent}}"
FontSize="{TemplateBinding FontSize}"/>
</Grid>
</Border>
<Canvas Canvas.Top="110">
<Button x:Name="decrease" Margin="20,0,0,0" Command="{Binding DecreaseCommand}" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" />
<Border Width="20" Height="20" >
<TextBlock Foreground="LightGray" Text="-" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Button x:Name="increase" Margin="60,0,0,0" Grid.Column="1" Command="{Binding IncreaseCommand}" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" />
<Border Width="20" Height="20" Grid.Column="1">
<TextBlock Foreground="LightGray" Text="+" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<!--<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" Margin="20,0,0,0"/>
<Border Width="20" Height="20" Margin="20,0,0,0">
<TextBlock Foreground="LightGray" Text="-" HorizontalAlignment="Center" />
</Border>
<Ellipse Width="20" Height="20" Stroke="LightGray" StrokeThickness="1" Margin="60,0,0,0"/>
<Border Width="20" Height="20" Margin="60,0,0,0">
<TextBlock Foreground="LightGray" Text="+" HorizontalAlignment="Center" />
</Border>-->
</Canvas>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
答案1
得分: 0
更改Convert
函数中的piang
计算,以便在计算中考虑底部左侧的起始点:
double piang = (angle + 36.8) * Math.PI / 180;
这样类会如下所示:
public class AngleToPointConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double angle = (double)value;
double radius = 50;
double piang = (angle + 36.8) * Math.PI / 180;
double px = Math.Sin(piang) * radius + radius;
double py = -Math.Cos(piang) * radius + radius;
return new System.Windows.Point(px, py);
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
您可能需要调整角度(36.8)。
英文:
change the piang calculation in the convert function so that the starting point at the bottom left is taken into account in the calculation
double piang = (angle - 143.2) * Math.PI / 180;
so the class looks like this
public class AngleToPointConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double angle = (double)value;
double radius = 50;
double piang = (angle - 143.2) * Math.PI / 180;
//double piang = angle * Math.PI / 310;
double px = Math.Sin(piang) * radius + radius;
double py = -Math.Cos(piang) * radius + radius;
return new System.Windows.Point(px, py);
}
public object ConvertBack(object value, Type targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
you may have to adjust the angle (143.2).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论