我正在从XAML元素创建XPS文件。不仅如此,我还创建了XPS文件,每个页面的大小可能不同。观看此最小复制品:
using (Package pkg = Package.Open("out.xps", FileMode.Create))
using (XpsDocument doc = new XpsDocument(pkg))
{
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
SerializerWriterCollator collator = writer.CreateVisualsCollator();
WritePage(816, 1344); // 8.5 x 14
WritePage(816, 1056); // 8.5 x 11
WritePage(816, 1344);
WritePage(816, 1056);
collator.EndBatchWrite();
doc.Close();
pkg.Close();
void WritePage(double width, double height)
{
var element = new Border()
{
Width = width,
Height = height,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(10.0)
};
Size size = new Size(width, height);
element.Measure(size);
element.Arrange(new Rect(size));
element.UpdateLayout();
collator.Write(element);
}
}
我遇到的问题是我所有页面的大小最终都一样。或更准确地说,与首页大小相同。该文档的页面全部显示为:
<FixedPage ... Width="816" Height="1344">
我解决此问题的第一个尝试是在写书时设置PrintTicket
,但没有效果。
稍后进行一些调试,我将问题追溯到WPF方法XpsSerializationManager.SaveAsXml
:
if (this._simulator == null)
{
this._simulator = new ReachHierarchySimulator(
(PackageSerializationManager) this, serializedObject);
}
...
if (this._isBatchMode)
{
xmlWriter = this._simulator.SimulateBeginFixedPage();
}
在这里,它仅在第一次调用_simulator
时初始化SaveAsXml
。存储在模拟器中的是serializedObject
-我们正在尝试保存的Visual
。问题是,此引用会留作以后的调用。
接下来,它调用_simulator.SimulateBeginFixedPage
来创建第一个<FixedPage>
元素-但由于它具有对原始对象的引用,因此每个页面都具有与该对象相同的大小。
因此,我解决的方法是在每次Write
调用之前通过反射更新该引用:
void WritePage(double width, double height)
{
var element = new Border()
{
Width = width,
Height = height,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(10.0),
Tag = pageCounter++
};
object manager = collator.GetType()
.GetField("_manager", BindingFlags.Instance | BindingFlags.NonPublic)
?.GetValue(collator);
object simulator = manager?.GetType()
.GetField("_simulator", BindingFlags.Instance | BindingFlags.NonPublic)
?.GetValue(manager);
simulator?.GetType()
.GetField("_serializedObject", BindingFlags.Instance | BindingFlags.NonPublic)
.SetValue(simulator, element);
Size size = new Size(width, height);
element.Measure(size);
element.Arrange(new Rect(size));
element.UpdateLayout();
collator.Write(element);
}
但是-我觉得这太奇怪了,可能是我使用WPF时遇到的问题,而不是WPF本身中的错误。有什么我想念的吗?