WPF如何将标签放在圆圈中间

WPF how to put label in the middle of circle

我有 WPF 申请和 Circle ProgressBar:

<Grid>
        <Path x:Name="pathRoot" Stroke="{Binding SegmentColor, ElementName=userControl}"
              StrokeThickness="{Binding StrokeThickness, ElementName=userControl}" 
              HorizontalAlignment="Left" VerticalAlignment="Top" Height="100" Width="100">
            <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>

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

    // 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)));

    // 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(60, 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 OnPercentageChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
    {
        CircularProgressBar circle = sender as CircularProgressBar;
        circle.Angle = (circle.Percentage * 360) / 100;
    }

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

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

这是我的 XAML 和我的 CircleProgressBar:

<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="54,507,54,75" Grid.Column="1" Height="138">
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Height="153" Width="155">
        <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center"
         SegmentColor="#FF878889" StrokeThickness="10" Percentage="100" />
        <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center"
         Percentage="33" SegmentColor="#FF5591E8" StrokeThickness="10"  />
    </Grid>
</StackPanel>

在这个控制器中,我找到 Label 显示我的 ProgressBar 百分比,但这个标签并不总是在 circle

的中间
    <Label Name="lblCircleProgress" Content="0%" Margin="116,561,100,127" Foreground="White" VerticalAlignment="Center" Grid.Column="1" />

所以我的问题是如何实现这个标签在百分比变化后一直在我的 Circle 中间?

也将它添加到网格中,删除那些边距并将 Horizo​​ntalAlignment 设置为居中。我看到您已经设置了 VerticalAlignment,因此它应该可以工作并且您应该在网格的中心看到它,并且考虑到您的 CircularProgressBar 也在网格内部,它应该看起来像预期的那样。

简化您的网格 - 并将所有内容放入其中。

这样一来,所有内容都会在同一视觉环境中水平和垂直居中。

<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Height="153" Width="155">
    <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center" 
                                         SegmentColor="#FF878889" StrokeThickness="10" Percentage="100" />
    <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center" 
                                         SegmentColor="#FF5591E8" StrokeThickness="10" Percentage="33" />            
    <Label Name="lblCircleProgress" Content="0%" Foreground="White" 
                                    HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>