UIElement.Rendersize不会随着窗口大小的改变而缩小
本文关键字:改变 缩小 窗口大小 Rendersize UIElement | 更新日期: 2023-09-27 17:51:02
遵循《WPF控件开发释放》一书中的示例,我修改了进度条以显示循环计时器。这包含一个围绕窗口中心逆时针运行的Arc(取决于我的ProgressBar的值)。
我的Arc
类继承自System.Windows.Shapes.Shape
,我使用RenderSize.Width
和RenderSize.Height
属性来缩放它取决于我的窗口大小。
这似乎工作得很好,但Rendersize似乎只增加。因此,当我扩展包含ProgressBar的窗口时,我的弧线可以完美地放大,但是当我再次缩小它时,弧线的大小并没有减少。
我的ControlTemplate包含一个网格,其中设置了所有元素(包括圆弧),因此所有其他不直接依赖于RenderSize的元素(一些省略号和一个文本块)可以根据需要缩放。
你知道为什么RenderSize的行为像描述的那样,哪些值我可以用来计算弧的开始/结束点的x/y坐标?
注意:如果我将网格的width
和height
设置为固定值,则渲染大小根本不会改变,这使我更加困惑,因为省略号和文本框已经相应地缩放网格。
我还读了《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值)。祝你好运!