Search code examples
c#data-bindingmauistring-formatting

Maui StringFormat in label, possible to change FontAttribute inline?


Really basic question, but I can't find the answer:

Is it possible to change the font attribute of a string in a label that's been formatted?

Specifically, I have this Label:

<Label Style="{StaticResource MediumLabel}"
       Text="{Binding TimeStart, StringFormat='Time start: {0:F0}'}" />

It ends up looking like this:

Time start: 13:32:46

When I would like it to look like this:

Time start: 13:32:46

Or this:

Time start: 13:32:46

Is this possible to do?


Solution

  • From the documentation Label exposes a FormattedText property that allows the presentation of text with multiple fonts and colors in the same view.

    We can create an IValueConverter to convert a string containing Markdown text into a FormattedString.

    // MarkDownConverter.cs
    public class MarkDownConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is null)
            {
                return null;
            }
    
            if (value is string str)
            {
                FormattedString formattedString = new FormattedString();
                Match match = Regex.Match(str, @"\*([^\*]*)\*|([^*]+)");
                while (match.Success)
                {
                    if (match.Groups[1].Success)
                    {
                        formattedString.Spans.Add(new Span() { Text = match.Groups[1].Value, FontAttributes = FontAttributes.Italic | FontAttributes.Bold });
                    }
                    if (match.Groups[2].Success)
                    {
                        formattedString.Spans.Add(new Span() { Text = match.Groups[2].Value, FontAttributes = FontAttributes.None });
                    }
                    match = match.NextMatch();
                }
                return formattedString;
            }
    
            return value;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    Then you can use it as follows:

    <!-- MainPage.xaml -->
    <ContentPage
        x:Class="MauiFormatApp.MainPage"
        xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:local="clr-namespace:MauiFormatApp"
        x:Name="mainPage"
        x:DataType="local:MainPage"
        BindingContext="{Reference mainPage}">
    
       <ContentPage.Resources>
           <ResourceDictionary>
               <local:MarkDownConverter x:Key="MarkDownConverter" />
           </ResourceDictionary>
       </ContentPage.Resources>
    
        <ScrollView>
            <VerticalStackLayout Padding="30,0" Spacing="25">
    
                <!-- Raw string -->
                <Label Text="{Binding Message}" />
    
                <!-- Formatted string -->
                <Label FormattedText="{Binding Message, Converter={StaticResource MarkDownConverter}}" />
    
            </VerticalStackLayout>
        </ScrollView>
    </ContentPage>
    
    // MainPage.xaml.cs
    public partial class MainPage : ContentPage
    {
        public string Message { get; set; } = "Time Start: *13:32:46*";
        public MainPage()
        {
            InitializeComponent();
        }
    }
    

    References: