VisualTreeHelper.GetDescendantBounds returns 'Empty'(无穷大)
VisualTreeHelper.GetDescendantBounds returns 'Empty' (Infinity)
在我的 WPF 应用程序中,我在运行时从 XML 动态加载 XAML 绘图。此图是一系列复杂的嵌套 canvas 和几何“路径”(例如):
<?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>
外部 canvas' Height/Width 设置不正确,因为许多路径表达式超出了这些尺寸。我无法控制此源 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;
}
然后,我尝试使用以下代码重置 canvas 大小:
var canvas = LoadDrawing(…);
someContentControOnTheExistingPage.Content = canvas;
var bounds = VisualTreeHelper.GetDescendantBounds(canvas); // << 'bounds' is empty here.
canvas.Width = bounds.Width;
canvas.Height = bounds.Height;
除此之外,在我创建 canvas 元素时,边界是空的。但是,如果我只是连接一个简单的按钮并在同一个 canvas 上以交互方式调用 GetDescendantBounds(),那么我会收到预期的 height/width.
我的结论是,除非新控件的布局已完成,否则 GetDescendantBounds() 不起作用。所以我的问题是:
- 有什么方法可以在 运行 GetDescendantBounds() 之前强制执行布局计算? 或者...
- 在将可视化树添加到其父级之前,是否有另一种方法可以获得可视化树的 bounds/extents?
谢谢
-约翰
首先,您需要在 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;
}
Is there a way I can force a layout computation prior to running GetDescendantBounds?
是,调用Canvas
的Arrange
和Measure
方法:
var canvas = LoadDrawing("...");
someContentControOnTheExistingPage.Content = canvas;
canvas.Arrange(new Rect(someContentControOnTheExistingPage.RenderSize));
canvas.Measure(someContentControOnTheExistingPage.RenderSize);
var bounds = VisualTreeHelper.GetDescendantBounds(canvas);
canvas.Width = bounds.Width;
canvas.Height = bounds.Height;
在我的 WPF 应用程序中,我在运行时从 XML 动态加载 XAML 绘图。此图是一系列复杂的嵌套 canvas 和几何“路径”(例如):
<?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>
外部 canvas' Height/Width 设置不正确,因为许多路径表达式超出了这些尺寸。我无法控制此源 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;
}
然后,我尝试使用以下代码重置 canvas 大小:
var canvas = LoadDrawing(…);
someContentControOnTheExistingPage.Content = canvas;
var bounds = VisualTreeHelper.GetDescendantBounds(canvas); // << 'bounds' is empty here.
canvas.Width = bounds.Width;
canvas.Height = bounds.Height;
除此之外,在我创建 canvas 元素时,边界是空的。但是,如果我只是连接一个简单的按钮并在同一个 canvas 上以交互方式调用 GetDescendantBounds(),那么我会收到预期的 height/width.
我的结论是,除非新控件的布局已完成,否则 GetDescendantBounds() 不起作用。所以我的问题是:
- 有什么方法可以在 运行 GetDescendantBounds() 之前强制执行布局计算? 或者...
- 在将可视化树添加到其父级之前,是否有另一种方法可以获得可视化树的 bounds/extents?
谢谢
-约翰
首先,您需要在 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;
}
Is there a way I can force a layout computation prior to running GetDescendantBounds?
是,调用Canvas
的Arrange
和Measure
方法:
var canvas = LoadDrawing("...");
someContentControOnTheExistingPage.Content = canvas;
canvas.Arrange(new Rect(someContentControOnTheExistingPage.RenderSize));
canvas.Measure(someContentControOnTheExistingPage.RenderSize);
var bounds = VisualTreeHelper.GetDescendantBounds(canvas);
canvas.Width = bounds.Width;
canvas.Height = bounds.Height;