WPF生成文本块内联线

WPF生成文本块内联线,wpf,binding,string-formatting,Wpf,Binding,String Formatting,我有一个GridView,在其中一个GridView列中,我想生成如下文本: textBlock.Text = string.Format("{0} is doing {1} .......", a, b); <GridViewColumn> <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock> <Hy

我有一个
GridView
,在其中一个
GridView列中,我想生成如下文本:

textBlock.Text = string.Format("{0} is doing {1} .......", a, b);
<GridViewColumn>
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock>
                <Hyperlink NavigateUri="{Binding AUri}">
                    <Run Text="{Binding A}"/>
                </Hyperlink>
                <Run Text=" is doing "/>
                <Hyperlink NavigateUri="{Binding BUri}">
                    <Run Text="{Binding B}"/>
                </Hyperlink>
            </TextBlock>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>
string inlineExpression = "Once i saw a little <bold>bird</bold>, <span>go <bold>hop, hop, hop</bold></span>.";
InlineExpression.SetInlineExpression(myTextBlock1, inlineExpression);
但是
a
b
(视图中项目的属性)不应仅表示为纯文本,而应表示为例如
超链接
(另外:文本格式应取决于项目类型)

如何以这种方式生成
TextBlock
s文本?(用于本地化)


问题更多:我应该自己写一些东西,还是框架提供了一种简单的方法?

在XAML中,您可以这样做:

textBlock.Text = string.Format("{0} is doing {1} .......", a, b);
<GridViewColumn>
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock>
                <Hyperlink NavigateUri="{Binding AUri}">
                    <Run Text="{Binding A}"/>
                </Hyperlink>
                <Run Text=" is doing "/>
                <Hyperlink NavigateUri="{Binding BUri}">
                    <Run Text="{Binding B}"/>
                </Hyperlink>
            </TextBlock>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>
string inlineExpression = "Once i saw a little <bold>bird</bold>, <span>go <bold>hop, hop, hop</bold></span>.";
InlineExpression.SetInlineExpression(myTextBlock1, inlineExpression);


在代码隐藏中,同样的事情也可以做,但我不推荐这样做,因为它涉及到使用。

最近我遇到了同样的问题。因此,我决定为
TextBlock
实现一个附加属性,该属性的值为
string
type,然后动态填充
Inlines
集合。您只需将属性值设置为以下值:

textBlock.Text = string.Format("{0} is doing {1} .......", a, b);
<GridViewColumn>
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock>
                <Hyperlink NavigateUri="{Binding AUri}">
                    <Run Text="{Binding A}"/>
                </Hyperlink>
                <Run Text=" is doing "/>
                <Hyperlink NavigateUri="{Binding BUri}">
                    <Run Text="{Binding B}"/>
                </Hyperlink>
            </TextBlock>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>
string inlineExpression = "Once i saw a little <bold>bird</bold>, <span>go <bold>hop, hop, hop</bold></span>.";
InlineExpression.SetInlineExpression(myTextBlock1, inlineExpression);
string inlineExpression=“有一次我看到一只小鸟,跳啊跳啊跳。”;
SetInlineExpression(myTextBlock1,InlineExpression);
还支持以下样式:

string inlineExpression = "<run style="Theme.GrayText">Once i saw a little bird, go hop, hop, hop.</run>";
InlineExpression.SetInlineExpression(myTextBlock1, inlineExpression);
string inlineExpression=“有一次我看到一只小鸟,跳啊跳啊跳。”;
SetInlineExpression(myTextBlock1,InlineExpression);
您还可以以标准方式在XAML中使用此附加属性

以下是公开此属性的类的代码:

public class InlineExpression
{
    public static readonly DependencyProperty InlineExpressionProperty = DependencyProperty.RegisterAttached(
        "InlineExpression", typeof(string), typeof(TextBlock), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure));

    public static void SetInlineExpression(TextBlock textBlock, string value)
    {
        textBlock.SetValue(InlineExpressionProperty, value);

        textBlock.Inlines.Clear();

        if (string.IsNullOrEmpty(value))
            return;

        var descriptions = GetInlineDescriptions(value);
        if (descriptions.Length == 0)
            return;

        var inlines = GetInlines(textBlock, descriptions);
        if (inlines.Length == 0)
            return;

        textBlock.Inlines.AddRange(inlines);
    }

    public static string GetInlineExpression(TextBlock textBlock)
    {
        return (string)textBlock.GetValue(InlineExpressionProperty);
    }

    enum InlineType
    {
        Run,
        LineBreak,
        Span,
        Bold,
        Italic,
        Hyperlink,
        Underline
    }

    class InlineDescription
    {
        public InlineType Type { get; set; }
        public string Text { get; set; }
        public InlineDescription[] Inlines { get; set; }
        public string StyleName { get; set; }
    }

    private static Inline[] GetInlines(FrameworkElement element, IEnumerable<InlineDescription> inlineDescriptions)
    {
        var inlines = new List<Inline>();
        foreach (var description in inlineDescriptions)
        {
            var inline = GetInline(element, description);
            if (inline != null)
                inlines.Add(inline);
        }

        return inlines.ToArray();
    }

    private static Inline GetInline(FrameworkElement element, InlineDescription description)
    {
        Style style = null;
        if (!string.IsNullOrEmpty(description.StyleName))
        {
            style = element.FindResource(description.StyleName) as Style;
            if (style == null)
                throw new InvalidOperationException("The style '" + description.StyleName + "' cannot be found");
        }

        Inline inline = null;
        switch (description.Type)
        {
            case InlineType.Run:
                var run = new Run(description.Text);
                inline = run;
                break;
            case InlineType.LineBreak:
                var lineBreak = new LineBreak();
                inline = lineBreak;
                break;
            case InlineType.Span:
                var span = new Span();
                inline = span;
                break;
            case InlineType.Bold:
                var bold = new Bold();
                inline = bold;
                break;
            case InlineType.Italic:
                var italic = new Italic();
                inline = italic;
                break;
            case InlineType.Hyperlink:
                var hyperlink = new Hyperlink();
                inline = hyperlink;
                break;
            case InlineType.Underline:
                var underline = new Underline();
                inline = underline;
                break;
        }

        if (inline != null)
        {
            var span = inline as Span;
            if (span != null)
            {
                var childInlines = new List<Inline>();
                foreach (var inlineDescription in description.Inlines)
                {
                    var childInline = GetInline(element, inlineDescription);
                    if (childInline == null)
                        continue;

                    childInlines.Add(childInline);
                }

                span.Inlines.AddRange(childInlines);
            }

            if (style != null)
                inline.Style = style;
        }

        return inline;
    }

    private static InlineDescription[] GetInlineDescriptions(string inlineExpression)
    {
        if (inlineExpression == null)
            return new InlineDescription[0];

        inlineExpression = inlineExpression.Trim();
        if (inlineExpression.Length == 0)
            return new InlineDescription[0];

        inlineExpression = inlineExpression.Insert(0, @"<root>");
        inlineExpression = inlineExpression.Insert(inlineExpression.Length, @"</root>");

        var xmlTextReader = new XmlTextReader(new StringReader(inlineExpression));
        var xmlDocument = new XmlDocument();
        xmlDocument.Load(xmlTextReader);

        var rootElement = xmlDocument.DocumentElement;
        if (rootElement == null)
            return new InlineDescription[0];

        var inlineDescriptions = new List<InlineDescription>();

        foreach (XmlNode childNode in rootElement.ChildNodes)
        {
            var description = GetInlineDescription(childNode);
            if (description == null)
                continue;

            inlineDescriptions.Add(description);
        }

        return inlineDescriptions.ToArray();
    }

    private static InlineDescription GetInlineDescription(XmlNode node)
    {
        var element = node as XmlElement;
        if (element != null)
            return GetInlineDescription(element);
        var text = node as XmlText;
        if (text != null)
            return GetInlineDescription(text);
        return null;
    }

    private static InlineDescription GetInlineDescription(XmlElement element)
    {
        InlineType type;
        var elementName = element.Name.ToLower();
        switch (elementName)
        {
            case "run":
                type = InlineType.Run;
                break;
            case "linebreak":
                type = InlineType.LineBreak;
                break;
            case "span":
                type = InlineType.Span;
                break;
            case "bold":
                type = InlineType.Bold;
                break;
            case "italic":
                type = InlineType.Italic;
                break;
            case "hyperlink":
                type = InlineType.Hyperlink;
                break;
            case "underline":
                type = InlineType.Underline;
                break;
            default:
                return null;
        }

        string styleName = null;
        var attribute = element.GetAttributeNode("style");
        if (attribute != null)
            styleName = attribute.Value;

        string text = null;
        var childDescriptions = new List<InlineDescription>();

        if (type == InlineType.Run || type == InlineType.LineBreak)
        {
            text = element.InnerText;
        }
        else
        {
            foreach (XmlNode childNode in element.ChildNodes)
            {
                var childDescription = GetInlineDescription(childNode);
                if (childDescription == null)
                    continue;

                childDescriptions.Add(childDescription);
            }
        }

        var inlineDescription = new InlineDescription
                                        {
                                            Type = type,
                                            StyleName = styleName,
                                            Text = text,
                                            Inlines = childDescriptions.ToArray()
                                        };

        return inlineDescription;
    }

    private static InlineDescription GetInlineDescription(XmlText text)
    {
        var value = text.Value;
        if (string.IsNullOrEmpty(value))
            return null;

        var inlineDescription = new InlineDescription
                                        {
                                            Type = InlineType.Run,
                                            Text = value
                                        };
        return inlineDescription;
    }
}
公共类InlineExpression
{
公共静态只读DependencyProperty InlineExpressionProperty=DependencyProperty.RegisterAttached(
“InlineExpression”、typeof(string)、typeof(TextBlock)、新FrameworkPropertyMetadata(string.Empty、FrameworkPropertyMetadataOptions.AffectsMeasure));
公共静态void SetInlineExpression(TextBlock TextBlock,字符串值)
{
SetValue(InlineExpressionProperty,值);
textBlock.Inlines.Clear();
if(string.IsNullOrEmpty(value))
返回;
变量描述=GetInlineDescriptions(值);
如果(descriptions.Length==0)
返回;
var inlines=GetInlines(文本块,描述);
如果(inlines.Length==0)
返回;
textBlock.Inlines.AddRange(Inlines);
}
公共静态字符串GetInlineExpression(TextBlock TextBlock)
{
返回(字符串)textBlock.GetValue(InlineExpressionProperty);
}
枚举内联类型
{
跑
断线,
跨度
大胆的
斜体,
超链接,
强调
}
类内联描述
{
公共InlineType类型{get;set;}
公共字符串文本{get;set;}
public InlineDescription[]Inlines{get;set;}
公共字符串样式名{get;set;}
}
私有静态内联[]GetInlines(FrameworkElement元素,IEnumerable inlineDescriptions)
{
var inlines=新列表();
foreach(inlineDescriptions中的变量描述)
{
var inline=GetInline(元素,描述);
如果(内联!=null)
inlines.Add(inline);
}
返回inlines.ToArray();
}
私有静态内联GetInline(FrameworkElement元素,InlineDescription)
{
Style=null;
如果(!string.IsNullOrEmpty(description.StyleName))
{
style=element.FindResource(description.StyleName)作为样式;
if(style==null)
抛出新的InvalidOperationException(“找不到样式“”+description.StyleName+”);
}
内联=空;
开关(说明.类型)
{
案例InlineType.Run:
var run=新运行(description.Text);
内联=运行;
打破
案例InlineType.LineBreak:
var lineBreak=新的lineBreak();
内联=换行符;
打破
案例InlineType.Span:
var span=新span();
内联=跨度;
打破
大小写InlineType.Bold:
var bold=new bold();
内联=粗体;
打破
大小写InlineType.Italic:
var italic=新斜体();
内联=斜体;
打破
案例InlineType.Hyperlink:
var hyperlink=新的hyperlink();
内联=超链接;
打破
大小写InlineType.Underline:
var underline=新下划线();
内联=下划线;
打破
}
如果(内联!=null)
{
var span=内联为span;
if(span!=null)
{
var childInlines=新列表();
foreach(description.Inlines中的变量inlineDescription)
{
var childInline=GetInline(元素,inlineDescription);
if(childInline==null)
继续;
添加(childInline);
}
span.Inlines.AddRange(childInlines);
}
如果(样式!=null)
inline.Style=Style;
}
内联返回;
}
私有静态InlineDescription[]GetInlineDescriptions(字符串inlineExpression)
{
if(inlineExpression==null)
返回新的InlineDescription[0];
inlineExpression=inlineExpression.Trim();
if(inlineExpression.Length==0)
返回新的InlineDescription[0];
inlineExpression=inlineExpression.Insert(0,@“”);
inl