/// <summary> /// Fill flow document paragraph with syntax colored XAML. /// </summary> /// <param name="paragraph">paragraph to be filled</param> /// <param name="xaml">xaml to colorize</param> /// <param name="styles">styles used for syntax coloring</param> public static void FillParagraph(this Paragraph paragraph, string xaml, XamlStyles styles) { using (var reader = new XmlTextReader(xaml, XmlNodeType.Document, null)) { var indent = 0; var tagOpened = false; while (reader.Read()) { if (reader.IsStartElement()) // opening tag, e.g. <Button { if (tagOpened) { // new line for child element paragraph.Inlines.Add(new LineBreak()); } // indentation paragraph.AddRun(new string(' ', indent * 4), styles.TextStyle); paragraph.AddRun("<", styles.DelimiterStyle); paragraph.AddRun(reader.Name, styles.NameStyle); if (reader.HasAttributes) { // write tag attributes while (reader.MoveToNextAttribute()) { paragraph.AddRun(" " + reader.Name, styles.AttributeStyle); paragraph.AddRun("=", styles.DelimiterStyle); paragraph.AddRun("\"", styles.QuotesStyle); string value; if (reader.Name == "TargetType") // target type fix - should use the Type MarkupExtension { value = "{x:Type " + reader.Value + "}"; } else { value = reader.Value; } paragraph.AddAttributeValue(value, styles); paragraph.AddRun("\"", styles.QuotesStyle); } reader.MoveToElement(); } if (reader.IsEmptyElement) // empty tag, e.g. <Button /> { paragraph.AddRun(" />", styles.DelimiterStyle); paragraph.Inlines.Add(new LineBreak()); tagOpened = false; --indent; } else // non-empty tag, e.g. <Button> { paragraph.AddRun(">", styles.DelimiterStyle); tagOpened = true; } ++indent; } else // closing tag, e.g. </Button> { --indent; // text content of a tag, e.g. the text "Do This" in <Button>Do This</Button> if (reader.NodeType == XmlNodeType.Text) { var content = reader.ReadContentAsString(); if (content.IndexOfAny(new[] { '\r', '\n' }) >= 0 && indent > 0) { // indentation paragraph.AddRun(new string(' ', indent * 4), styles.TextStyle); } paragraph.AddRun(content, styles.TextStyle); } else if (indent > 0) { // indentation paragraph.AddRun(new string(' ', indent * 4), styles.TextStyle); } paragraph.AddRun("</", styles.DelimiterStyle); paragraph.AddRun(reader.Name, styles.NameStyle); paragraph.AddRun(">", styles.DelimiterStyle); paragraph.Inlines.Add(new LineBreak()); tagOpened = false; } } } }