简体   繁体   中英

How do I bold portions of a bound TextBlock?

I have a TextBlock bound to a property. However, I'd like to bold certain words within the text. What is the easiest way to do this? FYI, I'm new to WPF.

Bolding individual words involves actually creating more inline elements, so you can't just bind a string to the TextBlock's Text and do this.

What I've done for this in the past is created a subclass of TextBlock which has a custom property that I bind to. When this property is bound I clear the Inlines of the base TextBlock and then use an algorithm that parses the new string value creating either plain Runs, Bolds, Hyperlinks etc.

Here's some sample code which I wrote for my experimental Twitter client which detects URLs, emails and @ pattern and creates hyperlinks for them. Regular text is inlined as normal runs:

[ContentProperty("StatusText")]
public sealed class StatusTextBlock : TextBlock
{
    #region Fields

    public static readonly DependencyProperty StatusTextProperty = DependencyProperty.Register(
                                                                                    "StatusText", 
                                                                                          typeof(string),
                                                                                    typeof(StatusTextBlock),
                                                                                    new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None, StatusTextBlock.StatusTextPropertyChangedCallback, null));
    private static readonly Regex UriMatchingRegex = new Regex(@"(?<url>[a-zA-Z]+:\/\/[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5}(:[0-9]{1,5})?([a-zA-Z0-9_\-\.\~\%\+\?\=\&\;\|/]*)?)|(?<emailAddress>[^\s]+@[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5})|(?<toTwitterScreenName>\@[a-zA-Z0-9\-_]+)", RegexOptions.Compiled);

    #endregion

    #region Constructors

    public StatusTextBlock()
    {
    }

    #endregion

    #region Type specific properties

    public string StatusText
    {
        get
        {
            return (string)this.GetValue(StatusTextBlock.StatusTextProperty);
        }

        set
        {
            this.SetValue(StatusTextBlock.StatusTextProperty, value);
        }
    }

    #endregion

    #region Helper methods

    internal static IEnumerable<Inline> GenerateInlinesFromRawEntryText(string entryText)
    {
        int startIndex = 0;
        Match match = StatusTextBlock.UriMatchingRegex.Match(entryText);

        while(match.Success)
        {
            if(startIndex != match.Index)
            {
                yield return new Run(StatusTextBlock.DecodeStatusEntryText(entryText.Substring(startIndex, match.Index - startIndex)));
            }

            Hyperlink hyperLink = new Hyperlink(new Run(match.Value));

            string uri = match.Value;

            if(match.Groups["emailAddress"].Success)
            {
                uri = "mailto:" + uri;
            }
            else if(match.Groups["toTwitterScreenName"].Success)
            {
                uri = "http://twitter.com/" + uri.Substring(1);
            }

            hyperLink.NavigateUri = new Uri(uri);

            yield return hyperLink;

            startIndex = match.Index + match.Length;

            match = match.NextMatch();
        }

        if(startIndex != entryText.Length)
        {
            yield return new Run(StatusTextBlock.DecodeStatusEntryText(entryText.Substring(startIndex)));
        }
    }

    internal static string DecodeStatusEntryText(string text)
    {
        return text.Replace("&gt;", ">").Replace("&lt;", "<");
    }

    private static void StatusTextPropertyChangedCallback(DependencyObject target, DependencyPropertyChangedEventArgs eventArgs)
    {
        StatusTextBlock targetStatusEntryTextBlock = (StatusTextBlock)target;

        targetStatusEntryTextBlock.Inlines.Clear();

        string newValue = eventArgs.NewValue as string;

        if(newValue != null)
        {
            targetStatusEntryTextBlock.Inlines.AddRange(StatusTextBlock.GenerateInlinesFromRawEntryText(newValue));
        }
    }

    #endregion
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM