我正在尝试为 Neo.Markdig.Xaml 制作 Markdown 渲染器。渲染器使用
XamlObjectWriter
来创建图形。在下面的代码中,我尝试创建一个包含单个段落的 FlowDocument
:
using System.Windows.Documents;
using System.Xaml;
XamlSchemaContext context = System.Windows.Markup.XamlReader.GetWpfSchemaContext()!;
using var writer = new XamlObjectWriter(context);
XamlType flowDocumentXamlType = context.GetXamlType(typeof(FlowDocument))!;
writer.WriteStartObject(flowDocumentXamlType);
XamlMember blocksXamlMember = flowDocumentXamlType.GetMember(nameof(FlowDocument.Blocks))!;
writer.WriteStartMember(blocksXamlMember);
XamlType paragraphXamlType = context.GetXamlType(typeof(Paragraph))!;
writer.WriteStartObject(paragraphXamlType);
XamlMember paragraphInlinesXamlMember = paragraphXamlType.GetMember(nameof(Paragraph.Inlines))!;
writer.WriteStartMember(paragraphInlinesXamlMember);
writer.WriteValue("Hello, world!");
writer.WriteEndMember();
writer.WriteEndObject(); // paragraphXamlType
writer.WriteEndMember(); // blocksXamlMember
writer.WriteEndObject(); // flowDocumentXamlType
但是它在
writer.WriteStartMember(paragraphInlinesXamlMember);
行抛出以下异常:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at System.Windows.Baml2006.WpfKnownMemberInvoker.SetValue(Object instance, Object value)
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)
at System.Xaml.XamlObjectWriter.Logic_ApplyPropertyValue(ObjectWriterContext ctx, XamlMember prop, Object value, Boolean onParent)
at System.Xaml.XamlObjectWriter.Logic_DoAssignmentToParentProperty(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
at System.Xaml.XamlObjectWriter.WriteStartMember(XamlMember property)
at Program.<Main>$(String[] args) in C:\TEMP\ConsoleApp1\Program.cs:line 13
我不知道我在这里做错了什么,而且关于这个主题的文档很少。
好的,找到了。当我们需要写一个集合时,我们必须有这两行:
writer.WriteGetObject();
writer.WriteStartMember(XamlLanguage.Items!);
所以我的代码变成:
using System.Windows.Documents;
using System.Xaml;
XamlSchemaContext context = System.Windows.Markup.XamlReader.GetWpfSchemaContext()!;
using var writer = new XamlObjectWriter(context);
XamlType flowDocumentXamlType = context.GetXamlType(typeof(FlowDocument))!;
writer.WriteStartObject(flowDocumentXamlType);
XamlMember blocks = flowDocumentXamlType.GetMember(nameof(FlowDocument.Blocks))!;
writer.WriteStartMember(blocks);
writer.WriteGetObject();
writer.WriteStartMember(XamlLanguage.Items!);
XamlType paragraphXamlType = context.GetXamlType(typeof(Paragraph))!;
writer.WriteStartObject(paragraphXamlType);
XamlMember inlines = paragraphXamlType.GetMember(nameof(Paragraph.Inlines))!;
writer.WriteStartMember(inlines);
writer.WriteGetObject();
writer.WriteStartMember(XamlLanguage.Items!);
writer.WriteValue("Hello, world!");
writer.WriteEndMember();
writer.WriteEndObject(); // paragraphXamlType
writer.WriteEndMember(); // blocksXamlMember
writer.WriteEndObject(); // flowDocumentXamlType
请不要问我为什么。
WriteGetObject()
的文档是:
当指定对象是父属性的默认值或隐式值时,将概念性 StartObject 写入对象图中。
🙃