WPF-Kreis Fortschrittsbalken

Möchte ich ersetzen den regulären ProgressBar mit Kreis ein und nach dem Schuß die Suche hier im forum habe ich gefunden, was ich will.

CircularProgressBar.XAML

<Grid>
    <Path x:Name="pathRoot" Stroke="{Binding SegmentColor, ElementName=userControl}" 
          StrokeThickness="{Binding StrokeThickness, ElementName=userControl}" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Path.Data>
            <PathGeometry>
                <PathGeometry.Figures>
                    <PathFigureCollection>
                        <PathFigure x:Name="pathFigure">
                            <PathFigure.Segments>
                                <PathSegmentCollection>
                                    <ArcSegment x:Name="arcSegment" SweepDirection="Clockwise" />
                                </PathSegmentCollection>
                            </PathFigure.Segments>
                        </PathFigure>
                    </PathFigureCollection>
                </PathGeometry.Figures>
            </PathGeometry>
        </Path.Data>
    </Path>
</Grid>

CircularProgressBar.cs:

public partial class CircularProgressBar : UserControl
{
    public CircularProgressBar()
    {
        InitializeComponent();
        Angle = (Percentage * 360) / 100;
        RenderArc();
    }

    public int Radius
    {
        get { return (int)GetValue(RadiusProperty); }
        set { SetValue(RadiusProperty, value); }
    }

    public Brush SegmentColor
    {
        get { return (Brush)GetValue(SegmentColorProperty); }
        set { SetValue(SegmentColorProperty, value); }
    }

    public int StrokeThickness
    {
        get { return (int)GetValue(StrokeThicknessProperty); }
        set { SetValue(StrokeThicknessProperty, value); }
    }

    public double Percentage
    {
        get { return (double)GetValue(PercentageProperty); }
        set { SetValue(PercentageProperty, value); }
    }

    public double Angle
    {
        get { return (double)GetValue(AngleProperty); }
        set { SetValue(AngleProperty, value); }
    }

    //Using a DependencyProperty as the backing store for Percentage.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty PercentageProperty =
        DependencyProperty.Register("Percentage", typeof(double), typeof(CircularProgressBar), new PropertyMetadata(65d, new PropertyChangedCallback(OnPercentageChanged)));

    //Using a DependencyProperty as the backing store for StrokeThickness.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StrokeThicknessProperty =
        DependencyProperty.Register("StrokeThickness", typeof(int), typeof(CircularProgressBar), new PropertyMetadata(5, new PropertyChangedCallback(OnThicknessChanged)));

    //Using a DependencyProperty as the backing store for SegmentColor.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SegmentColorProperty =
        DependencyProperty.Register("SegmentColor", typeof(Brush), typeof(CircularProgressBar), new PropertyMetadata(new SolidColorBrush(Colors.Red), new PropertyChangedCallback(OnColorChanged)));

    //Using a DependencyProperty as the backing store for Radius.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty RadiusProperty =
        DependencyProperty.Register("Radius", typeof(int), typeof(CircularProgressBar), new PropertyMetadata(25, new PropertyChangedCallback(OnPropertyChanged)));

    //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(120d, new PropertyChangedCallback(OnPropertyChanged)));

    private static void OnColorChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        CircularProgressBar circle = sender as CircularProgressBar;
        circle.set_Color((SolidColorBrush)args.NewValue);
    }

    private static void OnThicknessChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        CircularProgressBar circle = sender as CircularProgressBar;
        circle.set_tick((int)args.NewValue);
    }

    private static void OnPercentageChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        CircularProgressBar circle = sender as CircularProgressBar;
        if (circle.Percentage > 100) circle.Percentage = 100;
        circle.Angle = (circle.Percentage * 360) / 100;
    }

    private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        CircularProgressBar circle = sender as CircularProgressBar;
        circle.RenderArc();
    }

    public void set_tick(int n)
    {
        pathRoot.StrokeThickness = n;
    }

    public void set_Color(SolidColorBrush n)
    {
        pathRoot.Stroke = n;
    }

    public void RenderArc()
    {
        Point startPoint =  new Point(Radius, 0);
        Point endPoint = ComputeCartesianCoordinate(Angle, Radius);
        endPoint.X += Radius;
        endPoint.Y += Radius;

        pathRoot.Width = Radius * 2 + StrokeThickness;
        pathRoot.Height = Radius * 2 + StrokeThickness;
        pathRoot.Margin = new Thickness(StrokeThickness, StrokeThickness, 0, 0);

        bool largeArc = Angle > 180.0;

        Size outerArcSize = new Size(Radius, Radius);

        pathFigure.StartPoint = startPoint;

        if (startPoint.X == Math.Round(endPoint.X) && startPoint.Y == Math.Round(endPoint.Y))
            endPoint.X -= 0.01;

        arcSegment.Point = endPoint;
        arcSegment.Size = outerArcSize;
        arcSegment.IsLargeArc = largeArc;
    }

    private Point ComputeCartesianCoordinate(double angle, double radius)
    {
        //convert to radians
        double angleRad = (Math.PI / 180.0) * (angle - 90);

        double x = radius * Math.Cos(angleRad);
        double y = radius * Math.Sin(angleRad);

        return new Point(x, y);
    }
}

MainWindow.xaml:

    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center"
              SegmentColor="#FF878889" StrokeThickness="25" Percentage="100" />
            <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center"
              Percentage="{Binding Value, ElementName=slider}" SegmentColor="#026873" StrokeThickness="25" />
        </Grid>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </StackPanel>
    <Slider x:Name="slider" Grid.Row="1" Maximum="100" Value="60" />
</Grid>

Und das Ergebnis:

http://s21.postimg.org/xymj8k4pz/image.png

Also nach dem kopieren fügen Sie den gleichen code in meiner Lösung und läuft alles was ich sehe ist nur die Slider ohne die Circle Bar, das ist mein code:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="530,303,114,303">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center"
         SegmentColor="#FF878889" StrokeThickness="8" Percentage="100" />
        <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center"
         Percentage="{Binding Value, ElementName=slider}" SegmentColor="#026873" StrokeThickness="8" />
    </Grid>
</StackPanel>
<Slider x:Name="slider" Maximum="100" Value="20" Width="200" Margin="597,185,227,495" />

Mache ich etwas falsch ?

  • Pro-Tipp: Wenn Sie möchten, dass der Benutzer Kontrolle zu skalieren, mit seinen übergeordneten container, legen Sie das Raster und den Pfad innerhalb einer Viewbox.
  • Toller post! Danke!
Schreibe einen Kommentar