Markdown Display in WPF












2














I wanted to display a markdown document in WPF sensibly without relying on an HTML rendering system. I wrote a control based on the RichTextBox, and used Microsoft's markdown parser. What do you think?



XAML:



<RichTextBox x:Class="MarkdownViewer.MarkdownBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MarkdownViewer"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
x:Name="Content">
</RichTextBox>


C# backend for the XAML file:



public partial class MarkdownBox : RichTextBox
{
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(MarkdownBox), new UIPropertyMetadata(default(string), PropertyChangedCallback));

private static void PropertyChangedCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
{
if (source is MarkdownBox control)
{
var newValue = (string)args.NewValue;
switch (args.Property.Name)
{
case nameof(Text):
control.Text = newValue;
break;
}
}
}

public string Text
{
get => (string)GetValue(TextProperty);
set
{
var old = GetValue(TextProperty);
SetValue(TextProperty, value);
OnPropertyChanged(new DependencyPropertyChangedEventArgs(TextProperty, old, value));

SetTextboxContent();
}
}

public MarkdownBox()
{
InitializeComponent();
}

private void Hlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}

private void SetTextboxContent()
{
Content.Document.Blocks.Clear();

var doc = new MarkdownDocument();
doc.Parse(Text ?? string.Empty);

Content.Document.Blocks.AddRange(GetBlocks(doc.Blocks));
}

private IEnumerable<Block> GetBlocks(IList<MarkdownBlock> blocks)
{
foreach (var block in blocks)
{
switch (block)
{
case HeaderBlock header:
yield return GetHeaderBlock(header);
break;
case ParagraphBlock paragraph:
yield return GetParagraphBlock(paragraph);
break;
case ListBlock list:
yield return GetListBlock(list);
break;
case CodeBlock code:
yield return GetCodeBlock(code);
break;
case QuoteBlock quote:
yield return GetQuoteBlock(quote);
break;
case HorizontalRuleBlock rule:
yield return GetRuleBlock(rule);
break;
case TableBlock table:
yield return GetTableBlock(table);
break;
default:
throw new NotImplementedException();
}
}
}

private Block GetHeaderBlock(HeaderBlock header)
{
var headerLevels = new Dictionary<int, double>
{
[1] = 28,
[2] = 21,
[3] = 16.3833,
[4] = 14,
[5] = 11.6167,
[6] = 9.38333,
};

var content = header.Inlines.Select(GetInline);
var span = new Span();
span.Inlines.AddRange(content);

var labelElement = new Label
{
Content = span,
FontSize = headerLevels[header.HeaderLevel]
};
var blockElement = new BlockUIContainer(labelElement);
return blockElement;
}

private Block GetParagraphBlock(ParagraphBlock paragraph)
{
var paragraphElement = new Paragraph();
paragraphElement.Inlines.AddRange(paragraph.Inlines.Select(GetInline));
return paragraphElement;
}

private Block GetListBlock(ListBlock list)
{
var listElement = new List
{
MarkerStyle = list.Style == ListStyle.Bulleted ? TextMarkerStyle.Disc : TextMarkerStyle.Decimal
};
foreach (var item in list.Items)
{
var listItemElement = new ListItem();
listItemElement.Blocks.AddRange(GetBlocks(item.Blocks));
listElement.ListItems.Add(listItemElement);
}

return listElement;
}

private Block GetCodeBlock(CodeBlock code)
{
var typeConverter = new HighlightingDefinitionTypeConverter();
var avalon = new TextEditor
{
Text = code.Text,
SyntaxHighlighting = (IHighlightingDefinition)typeConverter.ConvertFrom("C#"),
FontFamily = new FontFamily("Consolas"),
FontSize = 12,
Padding = new Thickness(10),
BorderBrush = Brushes.LightGray,
BorderThickness = new Thickness(1),
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
IsReadOnly = true,
ShowLineNumbers = true,
MaxHeight = 250
};

return new BlockUIContainer(avalon);
}

private Block GetQuoteBlock(QuoteBlock quote)
{
var sectionElement = new Section
{
Background = new SolidColorBrush(Color.FromRgb(0xFF, 0xF8, 0xDC)),
BorderBrush = new SolidColorBrush(Color.FromRgb(0xff, 0xeb, 0x8e)),
BorderThickness = new Thickness(2, 0, 0, 0),
Padding = new Thickness(5)
};
var quoteBlocks = GetBlocks(quote.Blocks).ToList();
for (var i = 0; i < quoteBlocks.Count; i++)
{
var item = quoteBlocks[i];
item.Padding = new Thickness(5, 0, 5, 0);
item.Margin = new Thickness(0);
sectionElement.Blocks.Add(item);
}

return sectionElement;
}

private Block GetRuleBlock(HorizontalRuleBlock rule)
{
var line = new Line
{
Stretch = Stretch.Fill,
Stroke = Brushes.DarkGray,
X2 = 1
};
return new Paragraph(new InlineUIContainer(line));
}

private Block GetTableBlock(TableBlock table)
{
var alignments = new Dictionary<ColumnAlignment, TextAlignment>
{
[ColumnAlignment.Center] = TextAlignment.Center,
[ColumnAlignment.Left] = TextAlignment.Left,
[ColumnAlignment.Right] = TextAlignment.Right,
[ColumnAlignment.Unspecified] = TextAlignment.Justify
};

var tableElement = new Table
{
BorderThickness = new Thickness(0, 0, 1, 1),
BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
CellSpacing = 0
};
var tableRowGroup = new TableRowGroup();
for (int rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
{
var row = table.Rows[rowIndex];
var tableRow = new TableRow();

if (rowIndex % 2 == 0 && rowIndex != 0)
{
tableRow.Background = new SolidColorBrush(Color.FromRgb(0xf6, 0xf8, 0xfa));
}

for (int cellIndex = 0; cellIndex < row.Cells.Count; cellIndex++)
{
var cell = row.Cells[cellIndex];

var cellContent = new Paragraph();
cellContent.Inlines.AddRange(cell.Inlines.Select(GetInline));

var tableCell = new TableCell
{
TextAlignment = alignments[table.ColumnDefinitions[cellIndex].Alignment],
BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
BorderThickness = new Thickness(1, 1, 0, 0),
Padding = new Thickness(13, 6, 13, 6)
};
tableCell.Blocks.Add(cellContent);

if (rowIndex == 0)
{
tableCell.FontWeight = FontWeights.Bold;
}

tableRow.Cells.Add(tableCell);
}

tableRowGroup.Rows.Add(tableRow);
}
tableElement.RowGroups.Add(tableRowGroup);

return tableElement;
}

private Inline GetInline(MarkdownInline element)
{
switch (element)
{
case BoldTextInline bold:
return GetBoldInline(bold);
case TextRunInline text:
return GetTextRunInline(text);
case ItalicTextInline italic:
return GetItalicInline(italic);
case StrikethroughTextInline strikethrough:
return GetStrikethroughInline(strikethrough);
case CodeInline code:
return GetCodeInline(code);
case MarkdownLinkInline markdownLink:
return GetMarkdownLinkInline(markdownLink);
case HyperlinkInline hyperlink:
return GetHyperlinkInline(hyperlink);
case ImageInline image:
return GetImageInline(image);
case SubscriptTextInline subscript:
return GetSubscriptInline(subscript);
case SuperscriptTextInline superscript:
return GetSuperscriptInline(superscript);
default:
throw new NotImplementedException();
}
}

private Inline GetBoldInline(BoldTextInline bold)
{
var boldElement = new Bold();
foreach (var inline in bold.Inlines)
{
boldElement.Inlines.Add(GetInline(inline));
}
return boldElement;
}

private static Inline GetTextRunInline(TextRunInline text)
{
return new Run(text.ToString());
}

private Inline GetItalicInline(ItalicTextInline italic)
{
var italicElement = new Italic();
foreach (var inline in italic.Inlines)
{
italicElement.Inlines.Add(GetInline(inline));
}
return italicElement;
}

private Inline GetStrikethroughInline(StrikethroughTextInline strikethrough)
{
var strikethroughElement = new Span();
strikethroughElement.TextDecorations.Add(TextDecorations.Strikethrough);
foreach (var inline in strikethrough.Inlines)
{
strikethroughElement.Inlines.Add(GetInline(inline));
}
return strikethroughElement;
}

private static Inline GetCodeInline(CodeInline code)
{
return new Run(code.Text)
{
Background = new SolidColorBrush(Color.FromRgb(0xef, 0xf0, 0xf1))
};
}

private Inline GetMarkdownLinkInline(MarkdownLinkInline markdownLink)
{
var markdownLinkElement = new Hyperlink();
markdownLinkElement.Inlines.AddRange(markdownLink.Inlines.Select(GetInline));
markdownLinkElement.NavigateUri = new Uri(markdownLink.Url);
markdownLinkElement.ToolTip = markdownLink.Tooltip;
markdownLinkElement.RequestNavigate += Hlink_RequestNavigate;
return markdownLinkElement;
}

private Inline GetHyperlinkInline(HyperlinkInline hyperlink)
{
var hyperlinkElement = new Hyperlink();
hyperlinkElement.Inlines.Add(hyperlink.Text);
hyperlinkElement.NavigateUri = new Uri(hyperlink.Url);
hyperlinkElement.RequestNavigate += Hlink_RequestNavigate;
return hyperlinkElement;
}

private static Inline GetImageInline(ImageInline image)
{
var uri = new Uri(image.RenderUrl);
var bitmap = new BitmapImage(uri);
var imageElement = new Image
{
Source = bitmap,
Height = image.ImageHeight == 0 ? double.NaN : image.ImageHeight,
Width = image.ImageWidth == 0 ? double.NaN : image.ImageWidth,
ToolTip = image.Tooltip
};
return new InlineUIContainer(imageElement);
}

private Inline GetSubscriptInline(SubscriptTextInline subscript)
{
var subscriptElement = new Span();
subscriptElement.Typography.Variants = FontVariants.Subscript;
foreach (var inline in subscript.Inlines)
{
subscriptElement.Inlines.Add(GetInline(inline));
}
return subscriptElement;
}

private Inline GetSuperscriptInline(SuperscriptTextInline superscript)
{
var superscriptElement = new Span();
superscriptElement.Typography.Variants = FontVariants.Superscript;
foreach (var inline in superscript.Inlines)
{
superscriptElement.Inlines.Add(GetInline(inline));
}
return superscriptElement;
}
}









share|improve this question



























    2














    I wanted to display a markdown document in WPF sensibly without relying on an HTML rendering system. I wrote a control based on the RichTextBox, and used Microsoft's markdown parser. What do you think?



    XAML:



    <RichTextBox x:Class="MarkdownViewer.MarkdownBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:MarkdownViewer"
    mc:Ignorable="d"
    d:DesignHeight="450" d:DesignWidth="800"
    x:Name="Content">
    </RichTextBox>


    C# backend for the XAML file:



    public partial class MarkdownBox : RichTextBox
    {
    public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register(nameof(Text), typeof(string), typeof(MarkdownBox), new UIPropertyMetadata(default(string), PropertyChangedCallback));

    private static void PropertyChangedCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
    {
    if (source is MarkdownBox control)
    {
    var newValue = (string)args.NewValue;
    switch (args.Property.Name)
    {
    case nameof(Text):
    control.Text = newValue;
    break;
    }
    }
    }

    public string Text
    {
    get => (string)GetValue(TextProperty);
    set
    {
    var old = GetValue(TextProperty);
    SetValue(TextProperty, value);
    OnPropertyChanged(new DependencyPropertyChangedEventArgs(TextProperty, old, value));

    SetTextboxContent();
    }
    }

    public MarkdownBox()
    {
    InitializeComponent();
    }

    private void Hlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
    {
    Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
    e.Handled = true;
    }

    private void SetTextboxContent()
    {
    Content.Document.Blocks.Clear();

    var doc = new MarkdownDocument();
    doc.Parse(Text ?? string.Empty);

    Content.Document.Blocks.AddRange(GetBlocks(doc.Blocks));
    }

    private IEnumerable<Block> GetBlocks(IList<MarkdownBlock> blocks)
    {
    foreach (var block in blocks)
    {
    switch (block)
    {
    case HeaderBlock header:
    yield return GetHeaderBlock(header);
    break;
    case ParagraphBlock paragraph:
    yield return GetParagraphBlock(paragraph);
    break;
    case ListBlock list:
    yield return GetListBlock(list);
    break;
    case CodeBlock code:
    yield return GetCodeBlock(code);
    break;
    case QuoteBlock quote:
    yield return GetQuoteBlock(quote);
    break;
    case HorizontalRuleBlock rule:
    yield return GetRuleBlock(rule);
    break;
    case TableBlock table:
    yield return GetTableBlock(table);
    break;
    default:
    throw new NotImplementedException();
    }
    }
    }

    private Block GetHeaderBlock(HeaderBlock header)
    {
    var headerLevels = new Dictionary<int, double>
    {
    [1] = 28,
    [2] = 21,
    [3] = 16.3833,
    [4] = 14,
    [5] = 11.6167,
    [6] = 9.38333,
    };

    var content = header.Inlines.Select(GetInline);
    var span = new Span();
    span.Inlines.AddRange(content);

    var labelElement = new Label
    {
    Content = span,
    FontSize = headerLevels[header.HeaderLevel]
    };
    var blockElement = new BlockUIContainer(labelElement);
    return blockElement;
    }

    private Block GetParagraphBlock(ParagraphBlock paragraph)
    {
    var paragraphElement = new Paragraph();
    paragraphElement.Inlines.AddRange(paragraph.Inlines.Select(GetInline));
    return paragraphElement;
    }

    private Block GetListBlock(ListBlock list)
    {
    var listElement = new List
    {
    MarkerStyle = list.Style == ListStyle.Bulleted ? TextMarkerStyle.Disc : TextMarkerStyle.Decimal
    };
    foreach (var item in list.Items)
    {
    var listItemElement = new ListItem();
    listItemElement.Blocks.AddRange(GetBlocks(item.Blocks));
    listElement.ListItems.Add(listItemElement);
    }

    return listElement;
    }

    private Block GetCodeBlock(CodeBlock code)
    {
    var typeConverter = new HighlightingDefinitionTypeConverter();
    var avalon = new TextEditor
    {
    Text = code.Text,
    SyntaxHighlighting = (IHighlightingDefinition)typeConverter.ConvertFrom("C#"),
    FontFamily = new FontFamily("Consolas"),
    FontSize = 12,
    Padding = new Thickness(10),
    BorderBrush = Brushes.LightGray,
    BorderThickness = new Thickness(1),
    HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
    VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
    IsReadOnly = true,
    ShowLineNumbers = true,
    MaxHeight = 250
    };

    return new BlockUIContainer(avalon);
    }

    private Block GetQuoteBlock(QuoteBlock quote)
    {
    var sectionElement = new Section
    {
    Background = new SolidColorBrush(Color.FromRgb(0xFF, 0xF8, 0xDC)),
    BorderBrush = new SolidColorBrush(Color.FromRgb(0xff, 0xeb, 0x8e)),
    BorderThickness = new Thickness(2, 0, 0, 0),
    Padding = new Thickness(5)
    };
    var quoteBlocks = GetBlocks(quote.Blocks).ToList();
    for (var i = 0; i < quoteBlocks.Count; i++)
    {
    var item = quoteBlocks[i];
    item.Padding = new Thickness(5, 0, 5, 0);
    item.Margin = new Thickness(0);
    sectionElement.Blocks.Add(item);
    }

    return sectionElement;
    }

    private Block GetRuleBlock(HorizontalRuleBlock rule)
    {
    var line = new Line
    {
    Stretch = Stretch.Fill,
    Stroke = Brushes.DarkGray,
    X2 = 1
    };
    return new Paragraph(new InlineUIContainer(line));
    }

    private Block GetTableBlock(TableBlock table)
    {
    var alignments = new Dictionary<ColumnAlignment, TextAlignment>
    {
    [ColumnAlignment.Center] = TextAlignment.Center,
    [ColumnAlignment.Left] = TextAlignment.Left,
    [ColumnAlignment.Right] = TextAlignment.Right,
    [ColumnAlignment.Unspecified] = TextAlignment.Justify
    };

    var tableElement = new Table
    {
    BorderThickness = new Thickness(0, 0, 1, 1),
    BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
    CellSpacing = 0
    };
    var tableRowGroup = new TableRowGroup();
    for (int rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
    {
    var row = table.Rows[rowIndex];
    var tableRow = new TableRow();

    if (rowIndex % 2 == 0 && rowIndex != 0)
    {
    tableRow.Background = new SolidColorBrush(Color.FromRgb(0xf6, 0xf8, 0xfa));
    }

    for (int cellIndex = 0; cellIndex < row.Cells.Count; cellIndex++)
    {
    var cell = row.Cells[cellIndex];

    var cellContent = new Paragraph();
    cellContent.Inlines.AddRange(cell.Inlines.Select(GetInline));

    var tableCell = new TableCell
    {
    TextAlignment = alignments[table.ColumnDefinitions[cellIndex].Alignment],
    BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
    BorderThickness = new Thickness(1, 1, 0, 0),
    Padding = new Thickness(13, 6, 13, 6)
    };
    tableCell.Blocks.Add(cellContent);

    if (rowIndex == 0)
    {
    tableCell.FontWeight = FontWeights.Bold;
    }

    tableRow.Cells.Add(tableCell);
    }

    tableRowGroup.Rows.Add(tableRow);
    }
    tableElement.RowGroups.Add(tableRowGroup);

    return tableElement;
    }

    private Inline GetInline(MarkdownInline element)
    {
    switch (element)
    {
    case BoldTextInline bold:
    return GetBoldInline(bold);
    case TextRunInline text:
    return GetTextRunInline(text);
    case ItalicTextInline italic:
    return GetItalicInline(italic);
    case StrikethroughTextInline strikethrough:
    return GetStrikethroughInline(strikethrough);
    case CodeInline code:
    return GetCodeInline(code);
    case MarkdownLinkInline markdownLink:
    return GetMarkdownLinkInline(markdownLink);
    case HyperlinkInline hyperlink:
    return GetHyperlinkInline(hyperlink);
    case ImageInline image:
    return GetImageInline(image);
    case SubscriptTextInline subscript:
    return GetSubscriptInline(subscript);
    case SuperscriptTextInline superscript:
    return GetSuperscriptInline(superscript);
    default:
    throw new NotImplementedException();
    }
    }

    private Inline GetBoldInline(BoldTextInline bold)
    {
    var boldElement = new Bold();
    foreach (var inline in bold.Inlines)
    {
    boldElement.Inlines.Add(GetInline(inline));
    }
    return boldElement;
    }

    private static Inline GetTextRunInline(TextRunInline text)
    {
    return new Run(text.ToString());
    }

    private Inline GetItalicInline(ItalicTextInline italic)
    {
    var italicElement = new Italic();
    foreach (var inline in italic.Inlines)
    {
    italicElement.Inlines.Add(GetInline(inline));
    }
    return italicElement;
    }

    private Inline GetStrikethroughInline(StrikethroughTextInline strikethrough)
    {
    var strikethroughElement = new Span();
    strikethroughElement.TextDecorations.Add(TextDecorations.Strikethrough);
    foreach (var inline in strikethrough.Inlines)
    {
    strikethroughElement.Inlines.Add(GetInline(inline));
    }
    return strikethroughElement;
    }

    private static Inline GetCodeInline(CodeInline code)
    {
    return new Run(code.Text)
    {
    Background = new SolidColorBrush(Color.FromRgb(0xef, 0xf0, 0xf1))
    };
    }

    private Inline GetMarkdownLinkInline(MarkdownLinkInline markdownLink)
    {
    var markdownLinkElement = new Hyperlink();
    markdownLinkElement.Inlines.AddRange(markdownLink.Inlines.Select(GetInline));
    markdownLinkElement.NavigateUri = new Uri(markdownLink.Url);
    markdownLinkElement.ToolTip = markdownLink.Tooltip;
    markdownLinkElement.RequestNavigate += Hlink_RequestNavigate;
    return markdownLinkElement;
    }

    private Inline GetHyperlinkInline(HyperlinkInline hyperlink)
    {
    var hyperlinkElement = new Hyperlink();
    hyperlinkElement.Inlines.Add(hyperlink.Text);
    hyperlinkElement.NavigateUri = new Uri(hyperlink.Url);
    hyperlinkElement.RequestNavigate += Hlink_RequestNavigate;
    return hyperlinkElement;
    }

    private static Inline GetImageInline(ImageInline image)
    {
    var uri = new Uri(image.RenderUrl);
    var bitmap = new BitmapImage(uri);
    var imageElement = new Image
    {
    Source = bitmap,
    Height = image.ImageHeight == 0 ? double.NaN : image.ImageHeight,
    Width = image.ImageWidth == 0 ? double.NaN : image.ImageWidth,
    ToolTip = image.Tooltip
    };
    return new InlineUIContainer(imageElement);
    }

    private Inline GetSubscriptInline(SubscriptTextInline subscript)
    {
    var subscriptElement = new Span();
    subscriptElement.Typography.Variants = FontVariants.Subscript;
    foreach (var inline in subscript.Inlines)
    {
    subscriptElement.Inlines.Add(GetInline(inline));
    }
    return subscriptElement;
    }

    private Inline GetSuperscriptInline(SuperscriptTextInline superscript)
    {
    var superscriptElement = new Span();
    superscriptElement.Typography.Variants = FontVariants.Superscript;
    foreach (var inline in superscript.Inlines)
    {
    superscriptElement.Inlines.Add(GetInline(inline));
    }
    return superscriptElement;
    }
    }









    share|improve this question

























      2












      2








      2







      I wanted to display a markdown document in WPF sensibly without relying on an HTML rendering system. I wrote a control based on the RichTextBox, and used Microsoft's markdown parser. What do you think?



      XAML:



      <RichTextBox x:Class="MarkdownViewer.MarkdownBox"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="clr-namespace:MarkdownViewer"
      mc:Ignorable="d"
      d:DesignHeight="450" d:DesignWidth="800"
      x:Name="Content">
      </RichTextBox>


      C# backend for the XAML file:



      public partial class MarkdownBox : RichTextBox
      {
      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register(nameof(Text), typeof(string), typeof(MarkdownBox), new UIPropertyMetadata(default(string), PropertyChangedCallback));

      private static void PropertyChangedCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
      {
      if (source is MarkdownBox control)
      {
      var newValue = (string)args.NewValue;
      switch (args.Property.Name)
      {
      case nameof(Text):
      control.Text = newValue;
      break;
      }
      }
      }

      public string Text
      {
      get => (string)GetValue(TextProperty);
      set
      {
      var old = GetValue(TextProperty);
      SetValue(TextProperty, value);
      OnPropertyChanged(new DependencyPropertyChangedEventArgs(TextProperty, old, value));

      SetTextboxContent();
      }
      }

      public MarkdownBox()
      {
      InitializeComponent();
      }

      private void Hlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
      {
      Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
      e.Handled = true;
      }

      private void SetTextboxContent()
      {
      Content.Document.Blocks.Clear();

      var doc = new MarkdownDocument();
      doc.Parse(Text ?? string.Empty);

      Content.Document.Blocks.AddRange(GetBlocks(doc.Blocks));
      }

      private IEnumerable<Block> GetBlocks(IList<MarkdownBlock> blocks)
      {
      foreach (var block in blocks)
      {
      switch (block)
      {
      case HeaderBlock header:
      yield return GetHeaderBlock(header);
      break;
      case ParagraphBlock paragraph:
      yield return GetParagraphBlock(paragraph);
      break;
      case ListBlock list:
      yield return GetListBlock(list);
      break;
      case CodeBlock code:
      yield return GetCodeBlock(code);
      break;
      case QuoteBlock quote:
      yield return GetQuoteBlock(quote);
      break;
      case HorizontalRuleBlock rule:
      yield return GetRuleBlock(rule);
      break;
      case TableBlock table:
      yield return GetTableBlock(table);
      break;
      default:
      throw new NotImplementedException();
      }
      }
      }

      private Block GetHeaderBlock(HeaderBlock header)
      {
      var headerLevels = new Dictionary<int, double>
      {
      [1] = 28,
      [2] = 21,
      [3] = 16.3833,
      [4] = 14,
      [5] = 11.6167,
      [6] = 9.38333,
      };

      var content = header.Inlines.Select(GetInline);
      var span = new Span();
      span.Inlines.AddRange(content);

      var labelElement = new Label
      {
      Content = span,
      FontSize = headerLevels[header.HeaderLevel]
      };
      var blockElement = new BlockUIContainer(labelElement);
      return blockElement;
      }

      private Block GetParagraphBlock(ParagraphBlock paragraph)
      {
      var paragraphElement = new Paragraph();
      paragraphElement.Inlines.AddRange(paragraph.Inlines.Select(GetInline));
      return paragraphElement;
      }

      private Block GetListBlock(ListBlock list)
      {
      var listElement = new List
      {
      MarkerStyle = list.Style == ListStyle.Bulleted ? TextMarkerStyle.Disc : TextMarkerStyle.Decimal
      };
      foreach (var item in list.Items)
      {
      var listItemElement = new ListItem();
      listItemElement.Blocks.AddRange(GetBlocks(item.Blocks));
      listElement.ListItems.Add(listItemElement);
      }

      return listElement;
      }

      private Block GetCodeBlock(CodeBlock code)
      {
      var typeConverter = new HighlightingDefinitionTypeConverter();
      var avalon = new TextEditor
      {
      Text = code.Text,
      SyntaxHighlighting = (IHighlightingDefinition)typeConverter.ConvertFrom("C#"),
      FontFamily = new FontFamily("Consolas"),
      FontSize = 12,
      Padding = new Thickness(10),
      BorderBrush = Brushes.LightGray,
      BorderThickness = new Thickness(1),
      HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
      VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
      IsReadOnly = true,
      ShowLineNumbers = true,
      MaxHeight = 250
      };

      return new BlockUIContainer(avalon);
      }

      private Block GetQuoteBlock(QuoteBlock quote)
      {
      var sectionElement = new Section
      {
      Background = new SolidColorBrush(Color.FromRgb(0xFF, 0xF8, 0xDC)),
      BorderBrush = new SolidColorBrush(Color.FromRgb(0xff, 0xeb, 0x8e)),
      BorderThickness = new Thickness(2, 0, 0, 0),
      Padding = new Thickness(5)
      };
      var quoteBlocks = GetBlocks(quote.Blocks).ToList();
      for (var i = 0; i < quoteBlocks.Count; i++)
      {
      var item = quoteBlocks[i];
      item.Padding = new Thickness(5, 0, 5, 0);
      item.Margin = new Thickness(0);
      sectionElement.Blocks.Add(item);
      }

      return sectionElement;
      }

      private Block GetRuleBlock(HorizontalRuleBlock rule)
      {
      var line = new Line
      {
      Stretch = Stretch.Fill,
      Stroke = Brushes.DarkGray,
      X2 = 1
      };
      return new Paragraph(new InlineUIContainer(line));
      }

      private Block GetTableBlock(TableBlock table)
      {
      var alignments = new Dictionary<ColumnAlignment, TextAlignment>
      {
      [ColumnAlignment.Center] = TextAlignment.Center,
      [ColumnAlignment.Left] = TextAlignment.Left,
      [ColumnAlignment.Right] = TextAlignment.Right,
      [ColumnAlignment.Unspecified] = TextAlignment.Justify
      };

      var tableElement = new Table
      {
      BorderThickness = new Thickness(0, 0, 1, 1),
      BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
      CellSpacing = 0
      };
      var tableRowGroup = new TableRowGroup();
      for (int rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
      {
      var row = table.Rows[rowIndex];
      var tableRow = new TableRow();

      if (rowIndex % 2 == 0 && rowIndex != 0)
      {
      tableRow.Background = new SolidColorBrush(Color.FromRgb(0xf6, 0xf8, 0xfa));
      }

      for (int cellIndex = 0; cellIndex < row.Cells.Count; cellIndex++)
      {
      var cell = row.Cells[cellIndex];

      var cellContent = new Paragraph();
      cellContent.Inlines.AddRange(cell.Inlines.Select(GetInline));

      var tableCell = new TableCell
      {
      TextAlignment = alignments[table.ColumnDefinitions[cellIndex].Alignment],
      BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
      BorderThickness = new Thickness(1, 1, 0, 0),
      Padding = new Thickness(13, 6, 13, 6)
      };
      tableCell.Blocks.Add(cellContent);

      if (rowIndex == 0)
      {
      tableCell.FontWeight = FontWeights.Bold;
      }

      tableRow.Cells.Add(tableCell);
      }

      tableRowGroup.Rows.Add(tableRow);
      }
      tableElement.RowGroups.Add(tableRowGroup);

      return tableElement;
      }

      private Inline GetInline(MarkdownInline element)
      {
      switch (element)
      {
      case BoldTextInline bold:
      return GetBoldInline(bold);
      case TextRunInline text:
      return GetTextRunInline(text);
      case ItalicTextInline italic:
      return GetItalicInline(italic);
      case StrikethroughTextInline strikethrough:
      return GetStrikethroughInline(strikethrough);
      case CodeInline code:
      return GetCodeInline(code);
      case MarkdownLinkInline markdownLink:
      return GetMarkdownLinkInline(markdownLink);
      case HyperlinkInline hyperlink:
      return GetHyperlinkInline(hyperlink);
      case ImageInline image:
      return GetImageInline(image);
      case SubscriptTextInline subscript:
      return GetSubscriptInline(subscript);
      case SuperscriptTextInline superscript:
      return GetSuperscriptInline(superscript);
      default:
      throw new NotImplementedException();
      }
      }

      private Inline GetBoldInline(BoldTextInline bold)
      {
      var boldElement = new Bold();
      foreach (var inline in bold.Inlines)
      {
      boldElement.Inlines.Add(GetInline(inline));
      }
      return boldElement;
      }

      private static Inline GetTextRunInline(TextRunInline text)
      {
      return new Run(text.ToString());
      }

      private Inline GetItalicInline(ItalicTextInline italic)
      {
      var italicElement = new Italic();
      foreach (var inline in italic.Inlines)
      {
      italicElement.Inlines.Add(GetInline(inline));
      }
      return italicElement;
      }

      private Inline GetStrikethroughInline(StrikethroughTextInline strikethrough)
      {
      var strikethroughElement = new Span();
      strikethroughElement.TextDecorations.Add(TextDecorations.Strikethrough);
      foreach (var inline in strikethrough.Inlines)
      {
      strikethroughElement.Inlines.Add(GetInline(inline));
      }
      return strikethroughElement;
      }

      private static Inline GetCodeInline(CodeInline code)
      {
      return new Run(code.Text)
      {
      Background = new SolidColorBrush(Color.FromRgb(0xef, 0xf0, 0xf1))
      };
      }

      private Inline GetMarkdownLinkInline(MarkdownLinkInline markdownLink)
      {
      var markdownLinkElement = new Hyperlink();
      markdownLinkElement.Inlines.AddRange(markdownLink.Inlines.Select(GetInline));
      markdownLinkElement.NavigateUri = new Uri(markdownLink.Url);
      markdownLinkElement.ToolTip = markdownLink.Tooltip;
      markdownLinkElement.RequestNavigate += Hlink_RequestNavigate;
      return markdownLinkElement;
      }

      private Inline GetHyperlinkInline(HyperlinkInline hyperlink)
      {
      var hyperlinkElement = new Hyperlink();
      hyperlinkElement.Inlines.Add(hyperlink.Text);
      hyperlinkElement.NavigateUri = new Uri(hyperlink.Url);
      hyperlinkElement.RequestNavigate += Hlink_RequestNavigate;
      return hyperlinkElement;
      }

      private static Inline GetImageInline(ImageInline image)
      {
      var uri = new Uri(image.RenderUrl);
      var bitmap = new BitmapImage(uri);
      var imageElement = new Image
      {
      Source = bitmap,
      Height = image.ImageHeight == 0 ? double.NaN : image.ImageHeight,
      Width = image.ImageWidth == 0 ? double.NaN : image.ImageWidth,
      ToolTip = image.Tooltip
      };
      return new InlineUIContainer(imageElement);
      }

      private Inline GetSubscriptInline(SubscriptTextInline subscript)
      {
      var subscriptElement = new Span();
      subscriptElement.Typography.Variants = FontVariants.Subscript;
      foreach (var inline in subscript.Inlines)
      {
      subscriptElement.Inlines.Add(GetInline(inline));
      }
      return subscriptElement;
      }

      private Inline GetSuperscriptInline(SuperscriptTextInline superscript)
      {
      var superscriptElement = new Span();
      superscriptElement.Typography.Variants = FontVariants.Superscript;
      foreach (var inline in superscript.Inlines)
      {
      superscriptElement.Inlines.Add(GetInline(inline));
      }
      return superscriptElement;
      }
      }









      share|improve this question













      I wanted to display a markdown document in WPF sensibly without relying on an HTML rendering system. I wrote a control based on the RichTextBox, and used Microsoft's markdown parser. What do you think?



      XAML:



      <RichTextBox x:Class="MarkdownViewer.MarkdownBox"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="clr-namespace:MarkdownViewer"
      mc:Ignorable="d"
      d:DesignHeight="450" d:DesignWidth="800"
      x:Name="Content">
      </RichTextBox>


      C# backend for the XAML file:



      public partial class MarkdownBox : RichTextBox
      {
      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register(nameof(Text), typeof(string), typeof(MarkdownBox), new UIPropertyMetadata(default(string), PropertyChangedCallback));

      private static void PropertyChangedCallback(DependencyObject source, DependencyPropertyChangedEventArgs args)
      {
      if (source is MarkdownBox control)
      {
      var newValue = (string)args.NewValue;
      switch (args.Property.Name)
      {
      case nameof(Text):
      control.Text = newValue;
      break;
      }
      }
      }

      public string Text
      {
      get => (string)GetValue(TextProperty);
      set
      {
      var old = GetValue(TextProperty);
      SetValue(TextProperty, value);
      OnPropertyChanged(new DependencyPropertyChangedEventArgs(TextProperty, old, value));

      SetTextboxContent();
      }
      }

      public MarkdownBox()
      {
      InitializeComponent();
      }

      private void Hlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
      {
      Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
      e.Handled = true;
      }

      private void SetTextboxContent()
      {
      Content.Document.Blocks.Clear();

      var doc = new MarkdownDocument();
      doc.Parse(Text ?? string.Empty);

      Content.Document.Blocks.AddRange(GetBlocks(doc.Blocks));
      }

      private IEnumerable<Block> GetBlocks(IList<MarkdownBlock> blocks)
      {
      foreach (var block in blocks)
      {
      switch (block)
      {
      case HeaderBlock header:
      yield return GetHeaderBlock(header);
      break;
      case ParagraphBlock paragraph:
      yield return GetParagraphBlock(paragraph);
      break;
      case ListBlock list:
      yield return GetListBlock(list);
      break;
      case CodeBlock code:
      yield return GetCodeBlock(code);
      break;
      case QuoteBlock quote:
      yield return GetQuoteBlock(quote);
      break;
      case HorizontalRuleBlock rule:
      yield return GetRuleBlock(rule);
      break;
      case TableBlock table:
      yield return GetTableBlock(table);
      break;
      default:
      throw new NotImplementedException();
      }
      }
      }

      private Block GetHeaderBlock(HeaderBlock header)
      {
      var headerLevels = new Dictionary<int, double>
      {
      [1] = 28,
      [2] = 21,
      [3] = 16.3833,
      [4] = 14,
      [5] = 11.6167,
      [6] = 9.38333,
      };

      var content = header.Inlines.Select(GetInline);
      var span = new Span();
      span.Inlines.AddRange(content);

      var labelElement = new Label
      {
      Content = span,
      FontSize = headerLevels[header.HeaderLevel]
      };
      var blockElement = new BlockUIContainer(labelElement);
      return blockElement;
      }

      private Block GetParagraphBlock(ParagraphBlock paragraph)
      {
      var paragraphElement = new Paragraph();
      paragraphElement.Inlines.AddRange(paragraph.Inlines.Select(GetInline));
      return paragraphElement;
      }

      private Block GetListBlock(ListBlock list)
      {
      var listElement = new List
      {
      MarkerStyle = list.Style == ListStyle.Bulleted ? TextMarkerStyle.Disc : TextMarkerStyle.Decimal
      };
      foreach (var item in list.Items)
      {
      var listItemElement = new ListItem();
      listItemElement.Blocks.AddRange(GetBlocks(item.Blocks));
      listElement.ListItems.Add(listItemElement);
      }

      return listElement;
      }

      private Block GetCodeBlock(CodeBlock code)
      {
      var typeConverter = new HighlightingDefinitionTypeConverter();
      var avalon = new TextEditor
      {
      Text = code.Text,
      SyntaxHighlighting = (IHighlightingDefinition)typeConverter.ConvertFrom("C#"),
      FontFamily = new FontFamily("Consolas"),
      FontSize = 12,
      Padding = new Thickness(10),
      BorderBrush = Brushes.LightGray,
      BorderThickness = new Thickness(1),
      HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
      VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
      IsReadOnly = true,
      ShowLineNumbers = true,
      MaxHeight = 250
      };

      return new BlockUIContainer(avalon);
      }

      private Block GetQuoteBlock(QuoteBlock quote)
      {
      var sectionElement = new Section
      {
      Background = new SolidColorBrush(Color.FromRgb(0xFF, 0xF8, 0xDC)),
      BorderBrush = new SolidColorBrush(Color.FromRgb(0xff, 0xeb, 0x8e)),
      BorderThickness = new Thickness(2, 0, 0, 0),
      Padding = new Thickness(5)
      };
      var quoteBlocks = GetBlocks(quote.Blocks).ToList();
      for (var i = 0; i < quoteBlocks.Count; i++)
      {
      var item = quoteBlocks[i];
      item.Padding = new Thickness(5, 0, 5, 0);
      item.Margin = new Thickness(0);
      sectionElement.Blocks.Add(item);
      }

      return sectionElement;
      }

      private Block GetRuleBlock(HorizontalRuleBlock rule)
      {
      var line = new Line
      {
      Stretch = Stretch.Fill,
      Stroke = Brushes.DarkGray,
      X2 = 1
      };
      return new Paragraph(new InlineUIContainer(line));
      }

      private Block GetTableBlock(TableBlock table)
      {
      var alignments = new Dictionary<ColumnAlignment, TextAlignment>
      {
      [ColumnAlignment.Center] = TextAlignment.Center,
      [ColumnAlignment.Left] = TextAlignment.Left,
      [ColumnAlignment.Right] = TextAlignment.Right,
      [ColumnAlignment.Unspecified] = TextAlignment.Justify
      };

      var tableElement = new Table
      {
      BorderThickness = new Thickness(0, 0, 1, 1),
      BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
      CellSpacing = 0
      };
      var tableRowGroup = new TableRowGroup();
      for (int rowIndex = 0; rowIndex < table.Rows.Count; rowIndex++)
      {
      var row = table.Rows[rowIndex];
      var tableRow = new TableRow();

      if (rowIndex % 2 == 0 && rowIndex != 0)
      {
      tableRow.Background = new SolidColorBrush(Color.FromRgb(0xf6, 0xf8, 0xfa));
      }

      for (int cellIndex = 0; cellIndex < row.Cells.Count; cellIndex++)
      {
      var cell = row.Cells[cellIndex];

      var cellContent = new Paragraph();
      cellContent.Inlines.AddRange(cell.Inlines.Select(GetInline));

      var tableCell = new TableCell
      {
      TextAlignment = alignments[table.ColumnDefinitions[cellIndex].Alignment],
      BorderBrush = new SolidColorBrush(Color.FromRgb(0xdf, 0xe2, 0xe5)),
      BorderThickness = new Thickness(1, 1, 0, 0),
      Padding = new Thickness(13, 6, 13, 6)
      };
      tableCell.Blocks.Add(cellContent);

      if (rowIndex == 0)
      {
      tableCell.FontWeight = FontWeights.Bold;
      }

      tableRow.Cells.Add(tableCell);
      }

      tableRowGroup.Rows.Add(tableRow);
      }
      tableElement.RowGroups.Add(tableRowGroup);

      return tableElement;
      }

      private Inline GetInline(MarkdownInline element)
      {
      switch (element)
      {
      case BoldTextInline bold:
      return GetBoldInline(bold);
      case TextRunInline text:
      return GetTextRunInline(text);
      case ItalicTextInline italic:
      return GetItalicInline(italic);
      case StrikethroughTextInline strikethrough:
      return GetStrikethroughInline(strikethrough);
      case CodeInline code:
      return GetCodeInline(code);
      case MarkdownLinkInline markdownLink:
      return GetMarkdownLinkInline(markdownLink);
      case HyperlinkInline hyperlink:
      return GetHyperlinkInline(hyperlink);
      case ImageInline image:
      return GetImageInline(image);
      case SubscriptTextInline subscript:
      return GetSubscriptInline(subscript);
      case SuperscriptTextInline superscript:
      return GetSuperscriptInline(superscript);
      default:
      throw new NotImplementedException();
      }
      }

      private Inline GetBoldInline(BoldTextInline bold)
      {
      var boldElement = new Bold();
      foreach (var inline in bold.Inlines)
      {
      boldElement.Inlines.Add(GetInline(inline));
      }
      return boldElement;
      }

      private static Inline GetTextRunInline(TextRunInline text)
      {
      return new Run(text.ToString());
      }

      private Inline GetItalicInline(ItalicTextInline italic)
      {
      var italicElement = new Italic();
      foreach (var inline in italic.Inlines)
      {
      italicElement.Inlines.Add(GetInline(inline));
      }
      return italicElement;
      }

      private Inline GetStrikethroughInline(StrikethroughTextInline strikethrough)
      {
      var strikethroughElement = new Span();
      strikethroughElement.TextDecorations.Add(TextDecorations.Strikethrough);
      foreach (var inline in strikethrough.Inlines)
      {
      strikethroughElement.Inlines.Add(GetInline(inline));
      }
      return strikethroughElement;
      }

      private static Inline GetCodeInline(CodeInline code)
      {
      return new Run(code.Text)
      {
      Background = new SolidColorBrush(Color.FromRgb(0xef, 0xf0, 0xf1))
      };
      }

      private Inline GetMarkdownLinkInline(MarkdownLinkInline markdownLink)
      {
      var markdownLinkElement = new Hyperlink();
      markdownLinkElement.Inlines.AddRange(markdownLink.Inlines.Select(GetInline));
      markdownLinkElement.NavigateUri = new Uri(markdownLink.Url);
      markdownLinkElement.ToolTip = markdownLink.Tooltip;
      markdownLinkElement.RequestNavigate += Hlink_RequestNavigate;
      return markdownLinkElement;
      }

      private Inline GetHyperlinkInline(HyperlinkInline hyperlink)
      {
      var hyperlinkElement = new Hyperlink();
      hyperlinkElement.Inlines.Add(hyperlink.Text);
      hyperlinkElement.NavigateUri = new Uri(hyperlink.Url);
      hyperlinkElement.RequestNavigate += Hlink_RequestNavigate;
      return hyperlinkElement;
      }

      private static Inline GetImageInline(ImageInline image)
      {
      var uri = new Uri(image.RenderUrl);
      var bitmap = new BitmapImage(uri);
      var imageElement = new Image
      {
      Source = bitmap,
      Height = image.ImageHeight == 0 ? double.NaN : image.ImageHeight,
      Width = image.ImageWidth == 0 ? double.NaN : image.ImageWidth,
      ToolTip = image.Tooltip
      };
      return new InlineUIContainer(imageElement);
      }

      private Inline GetSubscriptInline(SubscriptTextInline subscript)
      {
      var subscriptElement = new Span();
      subscriptElement.Typography.Variants = FontVariants.Subscript;
      foreach (var inline in subscript.Inlines)
      {
      subscriptElement.Inlines.Add(GetInline(inline));
      }
      return subscriptElement;
      }

      private Inline GetSuperscriptInline(SuperscriptTextInline superscript)
      {
      var superscriptElement = new Span();
      superscriptElement.Typography.Variants = FontVariants.Superscript;
      foreach (var inline in superscript.Inlines)
      {
      superscriptElement.Inlines.Add(GetInline(inline));
      }
      return superscriptElement;
      }
      }






      c# wpf markdown






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 57 mins ago









      Hosch250

      17.2k565157




      17.2k565157



























          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210520%2fmarkdown-display-in-wpf%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210520%2fmarkdown-display-in-wpf%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Morgemoulin

          Scott Moir

          Souastre