htmluwphtml-agility-packrichtextblock

How to convert HTML to RTF in UWP


I want to convert HTML to RichTextBlock in UWP. I found some answers in stackoverflow tried the code in following link

link

But when I try to bind html property in richtextblock controls it gives error saying The name "Properties" does not exist in the namespace "using XAMLHtml"

I included following code to convert HTML to RTF in XAMLHtml.cs file

class XAMLHtml
{
    public class HtmlProperties : DependencyObject
    {
        public static readonly DependencyProperty HtmlProperty =
            DependencyProperty.RegisterAttached(
                "Html",
                typeof(string),
                typeof(HtmlProperties),
                new PropertyMetadata(null, HtmlChanged));

        private static RichTextBlock _currentObject;

        private static void HtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var richText = d as RichTextBlock;
            if (richText == null) return;

            _currentObject = richText;

            //Generate blocks
            var xhtml = e.NewValue as string;
            var blocks = GenerateBlocksForHtml(xhtml);

            _currentObject = null;

            //Add the blocks to the RichTextBlock
            richText.Blocks.Clear();
            foreach (var b in blocks)
                richText.Blocks.Add(b);
        }

        private static List<Block> GenerateBlocksForHtml(string xhtml)
        {
            var blocks = new List<Block>();

            try
            {
                var doc = new HtmlDocument();
                doc.LoadHtml(xhtml);

                var block = GenerateParagraph(doc.DocumentNode);
                blocks.Add(block);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }

            return blocks;
        }

        // TODO this method seams to be removing necessary spaces in #text nodes
        private static string CleanText(string input)
        {
            var clean = Windows.Data.Html.HtmlUtilities.ConvertToText(input);
            //clean = System.Net.WebUtility.HtmlEncode(clean);
            if (clean == "\0")
                clean = "\n";
            return clean;
        }

        private static Block GenerateBlockForTopNode(HtmlNode node)
            => GenerateParagraph(node);


        private static void AddChildren(Paragraph p, HtmlNode node)
        {
            var added = false;
            foreach (var child in node.ChildNodes)
            {
                var i = GenerateBlockForNode(child);
                if (i != null)
                {
                    p.Inlines.Add(i);
                    added = true;
                }
            }
            if (!added)
            {
                p.Inlines.Add(new Run { Text = CleanText(node.InnerText) });
            }
        }

        private static void AddChildren(Span s, HtmlNode node)
        {
            var added = false;

            foreach (var child in node.ChildNodes)
            {
                var i = GenerateBlockForNode(child);
                if (i != null)
                {
                    s.Inlines.Add(i);
                    added = true;
                }
            }
            if (!added)
            {
                s.Inlines.Add(new Run { Text = CleanText(node.InnerText) });
            }
        }

        private static Inline GenerateBlockForNode(HtmlNode node)
        {
            switch (node.Name)
            {


                case "b":
                case "B":
                case "strong":
                case "STRONG":
                    return GenerateBold(node);
                case "i":
                case "I":
                case "em":
                case "EM":
                    return GenerateItalic(node);
                case "u":
                case "U":
                    return GenerateUnderline(node);
                case "br":
                case "BR":
                    return new LineBreak();                                          
                default:
                    return GenerateSpanWNewLine(node);
            }

        }

        private static Inline GenerateBold(HtmlNode node)
        {
            var bold = new Bold();
            AddChildren(bold, node);
            return bold;
        }

        private static Inline GenerateUnderline(HtmlNode node)
        {
            var underline = new Underline();
            AddChildren(underline, node);
            return underline;
        }

        private static Inline GenerateItalic(HtmlNode node)
        {
            var italic = new Italic();
            AddChildren(italic, node);
            return italic;
        }

        private static Block GenerateParagraph(HtmlNode node)
        {
            var paragraph = new Paragraph();
            AddChildren(paragraph, node);
            return paragraph;
        }


        private static Inline GenerateSpanWNewLine(HtmlNode node)
        {
            var span = new Span();
            AddChildren(span, node);
            if (span.Inlines.Count > 0)
                span.Inlines.Add(new LineBreak());
            return span;
        }

    }
}

here what I write in xaml file

<Page
x:Class="SampleHtml.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
xmlns:converter="using XAMLHtml" 
xmlns:html="using HTMLPage1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <RichTextBlock converter:Properties.Html="{Binding HTMLPage1}" Grid.Row="0"/>
</Grid>

here is the code in html file

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <p><b>This text is bold</b></p>
    <p><i>This text is italic</i></p>
    <p>This is<sub> subscript</sub> and <sup>superscript</sup></p>
    
</body>
</html>

If anyone can help me with this I would appreciate.Thank you


Solution

  • This project is class lib for UWP platform. please download the full project and refer it.

    I check the code the class name is HtmlProperties but not Properties, so you need edit your xaml code like the following

    <RichTextBlock converter:HtmlProperties.Html="{x:Bind HtmlString}" />
    

    In general we could use WebViewBrush to get the webview content then set it the Rectangle control. for more please refer this document.