问问题
6144 次
2 回答
10
将其发布为其他与 FlowDocument/FixedDocument/XpsDocument 有类似呈现问题的其他人的未来参考。
需要注意的几点:
BlockUIContainers
使用上述方法时不会克隆。在我使用一些辅助方法将逻辑树打印出调试窗口之前,这并不是很明显(这些方法在下面发布 - 它们非常有用)。- 您需要在查看器中显示文档并在屏幕上简要显示。下面是我为我写的帮助方法。
强制渲染流文档
private static string ForceRenderFlowDocumentXaml =
@"<Window xmlns=""http://schemas.microsoft.com/netfx/2007/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<FlowDocumentScrollViewer Name=""viewer""/>
</Window>";
public static void ForceRenderFlowDocument(FlowDocument document)
{
using (var reader = new XmlTextReader(new StringReader(ForceRenderFlowDocumentXaml)))
{
Window window = XamlReader.Load(reader) as Window;
FlowDocumentScrollViewer viewer = LogicalTreeHelper.FindLogicalNode(window, "viewer") as FlowDocumentScrollViewer;
viewer.Document = document;
// Show the window way off-screen
window.WindowStartupLocation = WindowStartupLocation.Manual;
window.Top = Int32.MaxValue;
window.Left = Int32.MaxValue;
window.ShowInTaskbar = false;
window.Show();
// Ensure that dispatcher has done the layout and render passes
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Loaded, new Action(() => {}));
viewer.Document = null;
window.Close();
}
}
编辑:我刚刚添加window.ShowInTaskbar = false
到方法中,就好像你很快就可以看到窗口出现在任务栏中。
用户永远不会“看到”窗口,因为它位于屏幕外的位置Int32.MaxValue
- 这是早期多媒体创作(例如 Macromedia/Adobe Director)的常见技巧。
对于搜索和查找此问题的人,我可以告诉您,没有其他方法可以强制呈现文档。
视觉和逻辑树助手
public static string WriteVisualTree(DependencyObject parent)
{
if (parent == null)
return "No Visual Tree Available. DependencyObject is null.";
using (var stringWriter = new StringWriter())
using (var indentedTextWriter = new IndentedTextWriter(stringWriter, " "))
{
WriteVisualTreeRecursive(indentedTextWriter, parent, 0);
return stringWriter.ToString();
}
}
private static void WriteVisualTreeRecursive(IndentedTextWriter writer, DependencyObject parent, int indentLevel)
{
if (parent == null)
return;
int childCount = VisualTreeHelper.GetChildrenCount(parent);
string typeName = parent.GetType().Name;
string objName = parent.GetValue(FrameworkElement.NameProperty) as string;
writer.Indent = indentLevel;
writer.WriteLine(String.Format("[{0:000}] {1} ({2}) {3}", indentLevel,
String.IsNullOrEmpty(objName) ? typeName : objName,
typeName, childCount)
);
for (int childIndex = 0; childIndex < childCount; ++childIndex)
WriteVisualTreeRecursive(writer, VisualTreeHelper.GetChild(parent, childIndex), indentLevel + 1);
}
public static string WriteLogicalTree(DependencyObject parent)
{
if (parent == null)
return "No Logical Tree Available. DependencyObject is null.";
using (var stringWriter = new StringWriter())
using (var indentedTextWriter = new IndentedTextWriter(stringWriter, " "))
{
WriteLogicalTreeRecursive(indentedTextWriter, parent, 0);
return stringWriter.ToString();
}
}
private static void WriteLogicalTreeRecursive(IndentedTextWriter writer, DependencyObject parent, int indentLevel)
{
if (parent == null)
return;
var children = LogicalTreeHelper.GetChildren(parent).OfType<DependencyObject>();
int childCount = children.Count();
string typeName = parent.GetType().Name;
string objName = parent.GetValue(FrameworkElement.NameProperty) as string;
double actualWidth = (parent.GetValue(FrameworkElement.ActualWidthProperty) as double?).GetValueOrDefault();
double actualHeight = (parent.GetValue(FrameworkElement.ActualHeightProperty) as double?).GetValueOrDefault();
writer.Indent = indentLevel;
writer.WriteLine(String.Format("[{0:000}] {1} ({2}) {3}", indentLevel,
String.IsNullOrEmpty(objName) ? typeName : objName,
typeName,
childCount)
);
foreach (object child in LogicalTreeHelper.GetChildren(parent))
{
if (child is DependencyObject)
WriteLogicalTreeRecursive(writer, (DependencyObject)child, indentLevel + 1);
}
}
用法
#if DEBUG
Debug.WriteLine("--- Start -------");
Debug.WriteLine(VisualAndLogicalTreeHelper.WriteLogicalTree(document));
Debug.WriteLine("--- End -------");
#endif
于 2012-02-27T11:47:18.420 回答
7
于 2013-08-06T19:14:08.583 回答