0

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();
        }
    }

The result: enter image description here

Edit:

enter image description here

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>

enter image description here

wpf
  • 103
  • 6
  • 1
    Does this answer your question: https://stackoverflow.com/questions/16667072/how-to-draw-arc-with-radius-and-start-and-stop-angle ? It should let you define your start and end angles. – JonasH Jun 01 '23 at 11:10
  • Hi,@ JonasH. I'm not sure how I can use it, all my code is here, could you help me test it? I think there might be something wrong with the arc path calculation. – wpf Jun 01 '23 at 11:26
  • Hi,@ JonasH. I want the arc path to gradually fill the circle completely with the value of the progress Value. Just like the GIF edited in my question, only the start and end points are in the lower left corner. – wpf Jun 01 '23 at 11:35

1 Answers1

0

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).

EikeJoo
  • 64
  • 5
  • Hi,@EikeJoo. How can I change the progress value by dragging the ball? – wpf Jun 02 '23 at 05:33
  • Hi,@EikeJoo. Could you tell me what conditions are used to calculate the value about `143.2 ` in ` double piang = (angle - 143.2) * Math.PI / 180; ` ? – wpf Jun 05 '23 at 06:47
  • Hi,@EikeJoo. what value of StartPoint and angle in piang when radius is75? double angle = (double)value; double radius = 75; double piang = (angle - 143.2) * Math.PI / 180; – wpf Jun 05 '23 at 09:37