wpf 如何创建自定义进度条最小值0从左下角开始?

dojqjjoe  于 2023-06-07  发布在  其他
关注(0)|答案(1)|浏览(95)

我希望进度条的起点0%和终点100%位于左下角。并且值的进度更改为正常显示。我怎么才能做到呢?
我希望进度条的值沿着圆圈增减。
我的测试结果不正确,我不知道问题出在哪里,也不知道如何解决。
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();
        }
    }

结果:

编辑:

更新:
如何通过拖动球来更改进度值?

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

igsr9ssn

igsr9ssn1#

更改convert函数中的piang计算,以便在计算中考虑左下角的起点

double piang = (angle - 143.2) * 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 - 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();
    }
}

您可能需要调整Angular (143.2)。

相关问题