UIElement.Rendersize不会随着窗口大小的改变而缩小

本文关键字:改变 缩小 窗口大小 Rendersize UIElement | 更新日期: 2023-09-27 17:51:02

遵循《WPF控件开发释放》一书中的示例,我修改了进度条以显示循环计时器。这包含一个围绕窗口中心逆时针运行的Arc(取决于我的ProgressBar的值)。

我的Arc类继承自System.Windows.Shapes.Shape,我使用RenderSize.WidthRenderSize.Height属性来缩放它取决于我的窗口大小。

这似乎工作得很好,但Rendersize似乎只增加。因此,当我扩展包含ProgressBar的窗口时,我的弧线可以完美地放大,但是当我再次缩小它时,弧线的大小并没有减少。

我的ControlTemplate包含一个网格,其中设置了所有元素(包括圆弧),因此所有其他不直接依赖于RenderSize的元素(一些省略号和一个文本块)可以根据需要缩放。

你知道为什么RenderSize的行为像描述的那样,哪些值我可以用来计算弧的开始/结束点的x/y坐标?

注意:如果我将网格的widthheight设置为固定值,则渲染大小根本不会改变,这使我更加困惑,因为省略号和文本框已经相应地缩放网格。

UIElement.Rendersize不会随着窗口大小的改变而缩小

我还读了《WPF控制开发释放》这本书。看看时钟控制的比例问题。问题是当窗口改变其大小时,RenderSize没有改变。我的解决方案是添加一些逻辑的安排override和MessureOverride方法。

    private Size _finalSize;
    protected override Size MeasureOverride(Size availableSize)
    {
        Debug.WriteLine(string.Format("Mesure:{0},{1}", availableSize.Width, availableSize.Height));
        Size desiredSize = base.MeasureOverride(availableSize);
        _finalSize = availableSize;
        return desiredSize;
    }
    protected override Size ArrangeOverride(Size finalSize)
    {
        Debug.WriteLine(string.Format("Arrange:{0},{1}", _finalSize.Width, _finalSize.Height));
        base.ArrangeOverride(_finalSize);
        return _finalSize;
    }

=========================================================================我读了一些资料。他们说,measure和Arrange可以有相同的逻辑,但它们不应该共享数据。幸运的是,我找到了另一种解决方法。首先,控件应该具有拉伸依赖属性。然后改变ArcGeometry方法。

    static Arc()
    {
        StretchProperty.OverrideMetadata(typeof(Arc), new FrameworkPropertyMetadata(Stretch.Fill));
    }
    private Geometry GetArcGeometry2()
    {
        Point startPoint = PointAtAngle(RenderSize, Math.Min(StartAngle, EndAngle));
        Point endPoint = PointAtAngle(RenderSize, Math.Max(StartAngle, EndAngle));
        Point stopPoint = PointAtAngle(RenderSize, Math.Max(EndAngle, 359.99));//Add this
        Size arcSize = new Size(Math.Max(0, (RenderSize.Width - StrokeThickness)/2),
                                Math.Max(0, (RenderSize.Height - StrokeThickness)/2));
        bool isLargeArc = Math.Abs(EndAngle - StartAngle) > 180;
        StreamGeometry geom = new StreamGeometry();
        using (StreamGeometryContext context = geom.Open())
        {
            context.BeginFigure(startPoint, false, false);
            context.ArcTo(endPoint, arcSize, 0, isLargeArc, SweepDirection.Counterclockwise, true, false);
            context.ArcTo(stopPoint, arcSize, 0, !isLargeArc, SweepDirection.Counterclockwise, false, false);//add blank arc
        }
        geom.Transform = new TranslateTransform(StrokeThickness/2, StrokeThickness/2);
        return geom;
    }

我有一个类似的问题,并且(在查看了wwg2222的答案后)通过添加以下内容来解决它:

protected override Size MeasureOverride(Size constraint) => 
    new Size(constraint.Width, constraint.Height);

在此之后,形状大小正常,DefiningGeometry覆盖有适当的RenderSize可以使用。我不需要重写ArrangeOverride函数

我自己做了一个圆形的进度条,但我没有使用RenderSize。

一个更好的方法是在你的Arc上定义InnerRadius和OuterRadius属性,并让它们的值在0到1之间。

然后,在Arc的DefiningGeometry重写中进行计算。

因为圆弧是一个形状,你可以使用它的拉伸属性在控制模板中缩放它。

缩放的一个问题是弧的边界框会随着它的值/角度而变化。这就是为什么你需要在DefiningGeometry中定义一个EllipseGeometry来固定Arc的边界。由于这个额外的几何体,我甚至添加了第二个EllipseGeometry来获得正确的填充(因为FillRule)。EvenOdd值)。

祝你好运!