Feedback

Apps: BBCode in RichTextBlock binden

Sprache: C#

Diese angefügte Eigenschaft kann spezielle Formatierungen in Form von BBCode in einem RichTextBlock anzeigen. Das anzeigen kann dabei auch über eine Bindung geschehen Meine Implementierung kann Text Fett [ b ], Kursiv [ i ] oder eingefärbt [ Color=Farbe ] anzeigen. (Jeweils ohne den extra Leerzeichen in den eckigen Klammern.) Beendet wird die jeweilige Formatierung mit [/TagName]. Auch das Erstellen von Paragrafen mittels [p]…[/p] ist möglich. [b]Beispiel String[/b] [p]Paragraf 1[/p][p][b ]Fett [i]Fett & Kursiv[/b] Kursiv[/i][/p][p][color=red]Rot[/color] [color=green]Grün[/color] [color=#F09]RGB-Farbe: Magenta[/color][/p] [b]Hinweis: [/b]Leerzeichen hinter [b muss entfernt werden [b]Benötigte Namespaces[/b] System System.Collections.Generic Windows.UI Windows.UI.Text Windows.UI.Xaml Windows.UI.Xaml.Controls Windows.UI.Xaml.Documents Windows.UI.Xaml.Markup Windows.UI.Xaml.Media System.Linq
/// <summary>
/// Stellt Möglichkiten bereit um BBCode in einem <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/> anzuzeigen.
/// </summary>
public class RichTextBlockBBCode
{
    /// <summary>
    /// Ruft den per <see cref="SetBBCode"/> gesetzten BBCode ab.
    /// </summary>
    /// <param name="rtb">Der <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/> dessen BBCode abgerufen werden soll.</param>
    /// <returns>Der gesetzte BBCode des angegebenen Controls.</returns>
    public static string GetBBCode(RichTextBlock rtb)
    {
        return (string)rtb.GetValue(BBCodeProperty);
    }

    /// <summary>
    /// Setzt BBCode zum Anzeigen in einem <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/>.
    /// </summary>
    /// <param name="rtb">Der <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/>, für den der BBCode gesetzt werden soll.</param>
    /// <param name="bbcode">Der zu setzende BBCode.</param>
    public static void SetBBCode(RichTextBlock rtb, string bbcode)
    {
        rtb.SetValue(BBCodeProperty, bbcode);
    }

    /// <summary>
    /// Stellt die angefügte BBCode-Abhängigkeitseigenschaft dar.
    /// </summary>
    public static readonly DependencyProperty BBCodeProperty = DependencyProperty.RegisterAttached("BBCode", typeof(string), typeof(RichTextBlockBBCode), new PropertyMetadata(string.Empty, OnBBCodeChanged));

    private static void OnBBCodeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var rtb = d as RichTextBlock;
        var bcc = e.NewValue as string;

        rtb.Blocks.Clear();

        foreach (var item in bcc.Split(new string[] { "[p]", "[/p]" }, StringSplitOptions.RemoveEmptyEntries))
        {
            var p = new Paragraph();

            var formats = new List<string>();
            foreach (var s in SplitInBBCodeTags(item.ToCharArray()))
            {
                if (s.Length > 0 && s[0] == '[')
                {
                    if (s.Length > 2 && s[1] == '/')
                    {
                        var n = formats.FirstOrDefault(x => x == "[" + s.Substring(2) || x.StartsWith("[" + s.Substring(2, s.Length - 3) + "="));
                        if (n != null)
                            formats.Remove(n);
                    }
                    else
                    {
                        formats.Add(s);
                    }
                }
                else
                {
                    var run = CreateRun(formats);
                    run.Text = s;
                    p.Inlines.Add(run);
                }
            }

            rtb.Blocks.Add(p);
        }
    }

    static Run CreateRun(IEnumerable<string> formats)
    {
        var run = new Run();
        foreach (var format in formats)
        {
            switch (format)
            {
                case "[b]":
                    run.FontWeight = FontWeights.Bold;
                    break;
                case "[i]":
                    run.FontStyle = FontStyle.Italic;
                    break;
                default:
                    if (format.StartsWith("[color="))
                    {
                        try
                        {
                            var color = StringToColor(format.Substring(7, format.Length - 8));
                            run.Foreground = new SolidColorBrush(color);
                        }
                        catch { }
                    }
                    break;
            }
        }
        return run;
    }

    static Color StringToColor(string colorName)
    {
        string xaml = "<Color xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' >" + colorName + "</Color>";
        return (Color)XamlReader.Load(xaml);
    }

    static IEnumerable<string> SplitInBBCodeTags(char[] s)
    {
        int start = 0;
        for (int i = 1; i < s.Length; ++i)
        {
            if (s[i] == '[')
            {
                yield return new string(s, start, i - start);
                start = i;
            }
            if (s[i] == ']')
            {
                yield return new string(s, start, i - start + 1);
                start = i + 1;
            }
        }
        yield return new string(s, start, s.Length - start);
    }
}
/// <summary>
/// Stellt Möglichkiten bereit um BBCode in einem <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/> anzuzeigen.
/// </summary>
public class RichTextBlockBBCode
{
    /// <summary>
    /// Ruft den per <see cref="SetBBCode"/> gesetzten BBCode ab.
    /// </summary>
    /// <param name="rtb">Der <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/> dessen BBCode abgerufen werden soll.</param>
    /// <returns>Der gesetzte BBCode des angegebenen Controls.</returns>
    public static string GetBBCode(RichTextBlock rtb)
    {
        return (string)rtb.GetValue(BBCodeProperty);
    }

    /// <summary>
    /// Setzt BBCode zum Anzeigen in einem <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/>.
    /// </summary>
    /// <param name="rtb">Der <see cref="Windows.UI.Xaml.Controls.RichTextBlock"/>, für den der BBCode gesetzt werden soll.</param>
    /// <param name="bbcode">Der zu setzende BBCode.</param>
    public static void SetBBCode(RichTextBlock rtb, string bbcode)
    {
        rtb.SetValue(BBCodeProperty, bbcode);
    }

    /// <summary>
    /// Stellt die angefügte BBCode-Abhängigkeitseigenschaft dar.
    /// </summary>
    public static readonly DependencyProperty BBCodeProperty = DependencyProperty.RegisterAttached("BBCode", typeof(string), typeof(RichTextBlockBBCode), new PropertyMetadata(string.Empty, OnBBCodeChanged));

    private static void OnBBCodeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var rtb = d as RichTextBlock;
        var bcc = e.NewValue as string;

        rtb.Blocks.Clear();

        foreach (var item in bcc.Split(new string[] { "[p]", "[/p]" }, StringSplitOptions.RemoveEmptyEntries))
        {
            var p = new Paragraph();

            var formats = new List<string>();
            foreach (var s in SplitInBBCodeTags(item.ToCharArray()))
            {
                if (s.Length > 0 && s[0] == '[')
                {
                    if (s.Length > 2 && s[1] == '/')
                    {
                        var n = formats.FirstOrDefault(x => x == "[" + s.Substring(2) || x.StartsWith("[" + s.Substring(2, s.Length - 3) + "="));
                        if (n != null)
                            formats.Remove(n);
                    }
                    else
                    {
                        formats.Add(s);
                    }
                }
                else
                {
                    var run = CreateRun(formats);
                    run.Text = s;
                    p.Inlines.Add(run);
                }
            }

            rtb.Blocks.Add(p);
        }
    }

    static Run CreateRun(IEnumerable<string> formats)
    {
        var run = new Run();
        foreach (var format in formats)
        {
            switch (format)
            {
                case "[b]":
                    run.FontWeight = FontWeights.Bold;
                    break;
                case "[i]":
                    run.FontStyle = FontStyle.Italic;
                    break;
                default:
                    if (format.StartsWith("[color="))
                    {
                        try
                        {
                            var color = StringToColor(format.Substring(7, format.Length - 8));
                            run.Foreground = new SolidColorBrush(color);
                        }
                        catch { }
                    }
                    break;
            }
        }
        return run;
    }

    static Color StringToColor(string colorName)
    {
        string xaml = "<Color xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' >" + colorName + "</Color>";
        return (Color)XamlReader.Load(xaml);
    }

    static IEnumerable<string> SplitInBBCodeTags(char[] s)
    {
        int start = 0;
        for (int i = 1; i < s.Length; ++i)
        {
            if (s[i] == '[')
            {
                yield return new string(s, start, i - start);
                start = i;
            }
            if (s[i] == ']')
            {
                yield return new string(s, start, i - start + 1);
                start = i + 1;
            }
        }
        yield return new string(s, start, s.Length - start);
    }
}