Формат строки и форматированная строка - PullRequest
0 голосов
/ 26 сентября 2018

Я пытаюсь отформатировать строку, скажем

"Привет, Джордж, как дела?"

Я просто хочу "Джордж" в красном цвете.Есть ли способ использовать String.Format и FormattedString рядом?

Я пытался использовать:

var text = new FormattedString();
text.Spans.Add(new Span { 
    Text = Localize.GetString("irs", String.Empty), 
    ForegroundColor = Colors.RedColor 
});
label.FormattedText = String.Format(
    Localize.GetString("instructions", String.Empty), 
    text
);

Однако это не работает.Есть ли правильный способ сделать это на самом деле.Мне нужна локализация, поэтому я не хочу разбивать текст на несколько строк локализации.

1 Ответ

0 голосов
/ 27 сентября 2018

Вы можете использовать провайдера перехвата в string.Format.

В иллюстративных целях я выбираю формат XAML в качестве выходного, а затем преобразую его в FormattedString (но также можно использовать более сжатые форматы, такие как JSON).

Сначала давайте реализуем перехватпровайдер - который преобразует ваш string.Format вывод в Span (s):

public class InterceptProvider : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return this;
        else
            return null;
    }

    public string Format(String format, Object obj, IFormatProvider provider)
    {
        string spanText;

        // Use default for all other formatting.
        if (obj is IFormattable)
            spanText = ((IFormattable)obj).ToString(format, System.Globalization.CultureInfo.CurrentCulture);
        else
            spanText = obj.ToString();

        return $"</Span><Span ForegroundColor=\"Red\">{spanText}</Span><Span>";
    }
}

Добавьте метод расширения для интеграции перехватчика с string.Format.

public static class FormatExtensions
{
    static ColorTypeConverter _typeConverter = new ColorTypeConverter();
    static InterceptProvider _interceptor = new InterceptProvider();

    public static string InterceptFormat(this string sourceStr, params object[] args)
    {
        return $"<FormattedString><Span>{string.Format(_interceptor, sourceStr, args)}</Span></FormattedString>";
    }
* 1015И, наконец, вспомогательный метод, который преобразует XAML в FormattedString объект.
    public static FormattedString ToFormattedString(this string xamlStr)
    {
        var toReturn = new FormattedString();

        if (string.IsNullOrWhiteSpace(xamlStr))
            return toReturn;

        Span span = null;
        using(var strReader = new StringReader(xamlStr))
        {
            using(var xmlReader = XmlReader.Create(strReader))
            {
                while (xmlReader.Read())
                {

                    if (xmlReader.IsStartElement())
                    {
                        switch (xmlReader.Name)
                        {
                            case "Span":
                                span = new Span();

                                while (xmlReader.MoveToNextAttribute())
                                {
                                    switch (xmlReader.Name)
                                    {
                                        case "ForegroundColor":
                                            var color = xmlReader.Value;
                                            if (!string.IsNullOrEmpty(color))
                                                span.ForegroundColor = (Color)_typeConverter.ConvertFromInvariantString(color);
                                            break;
                                    }
                                }

                                if (xmlReader.IsStartElement() || xmlReader.MoveToContent() == XmlNodeType.Element)
                                {
                                    span.Text = xmlReader.ReadString();
                                    toReturn.Spans.Add(span ?? new Span());
                                }    

                                break;
                        }
                    }
                }
            }    
        }

        return toReturn;
    }

ИСПОЛЬЗОВАНИЕ:

label.FormattedText = Localize.GetString("instructions", String.Empty)
                          .InterceptFormat(text).ToFormattedString();

Или

lbl.FormattedText = "{0} It is now {1:d} at {1:t}"
                        .InterceptFormat("Morning!", DateTime.Now)
                        .ToFormattedString();

enter image description here

...