WPF:如何获得形状的真实大小(边界框)

Hor*_*Pen 4 .net c# wpf

我在获取Shapes的实际大小(边界框)方面遇到了麻烦.

我尝试使用RenderSize和ActualSize,但它们返回的值没有意义.但是,对于UIElements使用这些方法效果很好.

如果你可以帮助我,我会很有帮助的.

Fre*_*lad 11

你可以获得任何Visual使用的边界框TransformToVisual

所以,如果你有这样的Polygon定义

<Canvas Name="canvas">
    <Polygon Name="polygon" Canvas.Left="12" Canvas.Top="12"
             Points="0,75 100,0 100,150 0,75"
             Stroke="Purple"
             Fill="#9999ff"
             StrokeThickness="1"/>
</Canvas>
Run Code Online (Sandbox Code Playgroud)

然后,您可以Border使用以下代码在其边界框周围添加

private void AddBorderForFrameworkElement(FrameworkElement element)
{
    Rect bounds = element.TransformToVisual(canvas).TransformBounds(new Rect(element.RenderSize));
    Border boundingBox = new Border { BorderBrush = Brushes.Red, BorderThickness = new Thickness(1) };
    Canvas.SetLeft(boundingBox, bounds.Left);
    Canvas.SetTop(boundingBox, bounds.Top);
    boundingBox.Width = bounds.Width;
    boundingBox.Height = bounds.Height;
    canvas.Children.Add(boundingBox);            
}
Run Code Online (Sandbox Code Playgroud)

但是,使用此方法可能无法始终获得所需的结果,因为"边界框"并不总是实际绘制的边界.如果你在Polygon下面定义你喜欢的地方,你开始绘制x = 100的地方,那么边界框将比绘制的大得多

<Polygon Name="polygon" Canvas.Left="140" Canvas.Top="12"
         Points="100,75 200,0 200,150 100,75"
         Stroke="Purple"
         Fill="#9999ff"
         StrokeThickness="1"/>
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述
边界框比较


小智 5

我也遇到了这个问题,发现VisualContentBounds属性是一种获取形状的精确边界框的好方法,该边界框也包括笔触(如果有的话),并且几乎适用于我向其抛出的任何路径从WPF Visual类。问题在于它是内部的(通过Reflector找到),因此您只能将其用于内置WPF形状(因为您不能在程序集外部覆盖它),并且需要通过反射来获取它:

    Rect visualContentBounds = (Rect)GetPrivatePropertyValue(myShape, "VisualContentBounds");

    /*...*/

    private static object GetPrivatePropertyValue(object obj, string propName)
    {
        if (obj == null)
            throw new ArgumentNullException("obj");

        Type t = obj.GetType();
        PropertyInfo pi = t.GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        if (pi == null)
            throw new ArgumentOutOfRangeException("propName", string.Format("Field {0} was not found in Type {1}", propName, obj.GetType().FullName));

        return pi.GetValue(obj, null);
    }
Run Code Online (Sandbox Code Playgroud)