Display HTML with MAUI Label

In this post, I show how display HTML with NET8 MAUI Label using only the Label attributes. The source code of this post is available on GitHub.

Scenario

For my app, I want to display a sentence. Part of this sentence can be in bold or italics. So, I started to create an example using FlexLayout. First, I created a ContentView called FormattedMessage with this XAML:

<?xml version="1.0" encoding="utf-8" ?>
<ContentView
	x:Class="MauiTest.FormattedMessage"
	xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
	xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

	<FlexLayout
		BindableLayout.ItemsSource="{Binding FormattedText}"
		HorizontalOptions="FillAndExpand"
		VerticalOptions="FillAndExpand">
		<BindableLayout.ItemTemplate>
			<DataTemplate>
				<Label
					Padding="10"
					FontAttributes="{Binding FontAttributes}"
					Text="{Binding Text}"
					TextColor="{Binding TextColor}" />
			</DataTemplate>
		</BindableLayout.ItemTemplate>
	</FlexLayout>
</ContentView>

Code behind

Then, in the code for this view, I added the binding property

using MauiTest.Extensions;
using MauiTest.Models;

namespace MauiTest;

public partial class FormattedMessage : ContentView
{
	public IList<FormattedText>? FormattedText { get; set; }

	public static readonly BindableProperty MessageProperty = 
		BindableProperty.Create(nameof(Message), typeof(IList<FormattedText>), 
			typeof(FormattedMessage), null);

	public string Message
	{
		get => (string)GetValue(MessageProperty);
		set
		{
			SetValue(MessageProperty, value);
            FormattedText = value.GetFormattedMessage();
			OnPropertyChanged(nameof(FormattedText));
        }
	}

	public FormattedMessage()
	{
		InitializeComponent();
		BindingContext = this;
	}
}

FormattedText model

Now, each part of the sentence I want to display has to be define using this model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MauiTest.Models
{
    /// <summary>
    /// Class FormattedText.
    /// </summary>
    public class FormattedText
    {
        /// <summary>
        /// Gets or sets the font attributes.
        /// </summary>
        /// <value>The font attributes.</value>
        public FontAttributes FontAttributes { get; set; } = FontAttributes.None;

        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>The text.</value>
        public string? Text { get; set; }

        /// <summary>
        /// Gets or sets the color of the text.
        /// </summary>
        /// <value>The color of the text.</value>
        public Color TextColor { get; set; } = Colors.Black;
    }
}

String Extension

I split the string in chunks. I defined that when I find a star *, I want that part of the string in bold. Using RegEx, I split the string and add the part of the string to the IList<FormattedText>.

using MauiTest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace MauiTest.Extensions
{
    public static class StringExtensions
    {
        public static IList<FormattedText> GetFormattedMessage(this string message)
        {
            List<FormattedText> Result = new List<FormattedText>();
            string pat = @"\*([^\*]*)\*|([^*]+)";
            Match match = Regex.Match(message, pat);
            while (match.Success)
            {
                if (match.Groups[1].Success)
                {
                    Result.Add(new FormattedText() { Text = match.Groups[1].Value, 
                        FontAttributes = FontAttributes.Bold });
                }
                if (match.Groups[2].Success)
                {
                    Result.Add(new FormattedText() { Text = match.Groups[2].Value, 
                        FontAttributes = FontAttributes.None });
                }
                match = match.NextMatch();
            }
            return Result;
        }
    }
}

Put together

Now, putting everything together, the result is not what I expected.

FlexLayout is not rendering the words in the correct way. As a test, I change FlexLayout with a VerticalLayout and I can see every part of the sentence with the correct attributes

Solution

I didn’t know that now Label has a new attribute TextType and I can pass HTML code

<Label 
    Text="Lorem ipsum dolor sit amet, &lt;b>consectetur adipiscing elit&lt;/b>." 
    TextType="Html" />

The only thing is to replace the char < with &lt;. Also, it is possible to add this code

<Label TextType="Html">
    <![CDATA[
        <p>Este es el primer párrafo con <u>texto subrayado</u>.</p>
        <p>segundo párrafo, donde parte del <del>texto está tachado</del>.</p>
    ]]>
</Label>

From the C#, I can write

Label label = new Label
{
    TextType = TextType.Html,
    Text = "<p>Este es el primer párrafo con <u>texto subrayado</u>.</p>" +
      "<p>segundo párrafo, donde parte del <del>texto está tachado</del>.</p>"
};

I hope this can help someone. Happy coding!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.