VisualTreeHelper.GetDescendantBounds返回' Empty' (无限远)

时间:2017-04-24 21:03:04

标签: wpf xaml visualtreehelper

在我的WPF应用程序中,我在运行时从XML动态加载XAML绘图。此图是一系列复杂的嵌套画布和几何图形(例如):

<?xml version="1.0" encoding="utf-8"?>
<Canvas Width="1593" Height="1515">
    <Canvas.Resources />
    <Canvas>
        <Path Fill="…" Data="…"/>
        <Path Fill="…" Data="…"/>
        <Path Fill="…" Data="…"/>
        <Canvas>
            <Canvas>
                <Path Stroke="…" StrokeThickness="…" StrokeMiterLimit="…" StrokeLineJoin="…" StrokeEndLineCap="…" Data="…"/>
                <Path Stroke="…" StrokeThickness="…" StrokeMiterLimit="…" StrokeLineJoin="…" StrokeEndLineCap="…" Data="…"/>
            </Canvas>
        </Canvas>
        <Path Fill="…" Data="…"/>
        <Path Fill="…" Data="…"/>
        <Path Fill="…" Data="…"/>
    </Canvas>
</Canvas>

外部帆布&#39;高度/宽度设置不正确,因为许多路径表达式超出了这些尺寸。我无法控制此源XML,因此我需要在加载绘图后在运行时修复它。要加载图形,我使用类似于以下代码:

public static Canvas LoadDrawing(string xaml)
{
    Canvas drawing = null;
    using (var stringreader = new StringReader(xaml))
    {
        using (var xmlReader = new XmlTextReader(stringreader))
        {
            drawing = (Canvas)XamlReader.Load(xmlReader);
        }
    }
    return drawing;
}

然后,我尝试使用以下代码重置画布大小:

    var canvas = LoadDrawing(…);
    someContentControOnTheExistingPage.Content = canvas;
    var bounds = VisualTreeHelper.GetDescendantBounds(canvas); // << 'bounds' is empty here.
    canvas.Width = bounds.Width;
    canvas.Height = bounds.Height;

除了在我创建canvas元素的时候,边界是空的。但是,如果我只是连接一个简单的按钮并在同一个画布上以交互方式调用GetDescendantBounds(),那么我会收到预期的高度/宽度。

我的看法是,除非已完成具有新控件的布局,否则GetDescendantBounds()不起作用。所以我的问题是:

  1. 有没有办法可以在运行GetDescendantBounds()之前强制进行布局计算?或......
  2. 在将可视化树添加到其父级之前,是否有另一种方法可以获取可视树的边界/范围?
  3. 由于

    -John

2 个答案:

答案 0 :(得分:0)

首先,您需要在xaml字符串中添加此行。

xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'

这是查找控件和属性的C#代码示例。

 public void LoadXaml()
    {
        string canvasString = @"<Canvas Name='canvas1' xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Width = '1593' Height = '1515'> </Canvas>";
        var canvas = LoadDrawing(canvasString);

        //Use this line you will find height and width.
        Canvas canvasCtrl = (Canvas)LogicalTreeHelper.FindLogicalNode(canvas, "canvas1");

        // var bounds = VisualTreeHelper.GetDescendantBounds(canvas); // << 'bounds' is empty here.

        canvas.Width = canvasCtrl.Width; //bounds.Width;
        canvas.Height = canvasCtrl.Height; //bounds.Height;
    }

答案 1 :(得分:0)

  

有没有办法在运行GetDescendantBounds之前强制进行布局计算?

是的,请致电Arrange的{​​{1}}和Measure方法:

Canvas