我正在尝试格式化一个可以说的字符串
“你好,乔治,你好吗?”
我只想要红色的“乔治”。有什么办法可以并排使用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
);
但是,这不起作用。是否有任何适当的方法来实际执行此操作。我想要本地化,所以我不想将文本拆分成多个本地化字符串。
答案 0 :(得分:1)
您可以在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>";
}
最后是一个将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();