【问题标题】:Embedded hyperlinks in WPF and localizationWPF 中的嵌入式超链接和本地化
【发布时间】:2012-05-22 02:17:08
【问题描述】:

我在 WPF 应用程序中有一个 TextBlock,我想向用户显示类似于以下内容的消息:

Retrygo back.

我可以这样做:

<TextBlock>
    <Hyperlink Command="{Binding RetryCommand}">
        <Run Text="Retry" />
    </Hyperlink>
    <Run Text=" or " />
    <Hyperlink Command="{Binding GoBackCommand}">
        <Run Text="go back." />
    </Hyperlink>
</TextBlock>

但是,这种方案对本地化不是很友好;在本地化过程中需要重新排列句子的情况下尤其成问题。我更希望能够在 resx 文件中指定 "[Retry]({0}) or [go back.]({1})." 之类的内容,并将超链接动态插入到本地化字符串中。有没有一种干净简单的方法可以做到这一点?

在另一个应用程序中,我们使用了一个非常复杂的解决方案,包括扩展 TextBlock 类和动态构造 Inlines 属性,但对于一个应该是常见问题的问题,它似乎有很多代码。

相关问题:Is adding strings with placeholders (`{0}`) into resources a good idea?How to embed links in localized text

【问题讨论】:

    标签: wpf localization hyperlink


    【解决方案1】:

    所以我想一种解决方案是自定义控件。但是,我能够使用 IMultiValueConverter 来完成工作。

    public class TextBlockFormatToHyperlinkConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (values.Length >= 3)
            {
                var tblk = values[0] as TextBlock;
                var format = values[1] as string;
                var tokens = Tokenizer.ParseTokens(format);
                int hyperLinkIndex = 0;
                for (int i = 2; i < values.Length; i++)
                {
                    var token = tokens.FirstOrDefault((p) => string.Equals(p.Value as string, "{" + hyperLinkIndex + "}"));
                    if (token != null)
                    {
                        token.Value = values[i];
                    }
                    hyperLinkIndex++;
                }
    
                tblk.Inlines.Clear();
                foreach (var token in tokens)
                {
                    if (token.Value is Hyperlink)
                        tblk.Inlines.Add((Hyperlink)token.Value);
                    else
                        tblk.Inlines.Add(new Run(token.Value as string));
                }
    
                return tblk;
            }
            return null;
        }
    
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    
        private class Token
        {
            public object Value { get; set; }
            public Token(object value)
            {
                Value = value;
            }
        }
        private class HyperlinkToken : Token
        {
            public HyperlinkToken(object value) : base(value) { }
        }
    
        private static class Tokenizer
        {
            public static List<Token> ParseTokens(string format)
            {
                var tokens = new List<Token>();
                var strings = Regex.Split(format, @"({\d+})");
                foreach (var str in strings)
                {
                    if (Regex.IsMatch(str, @"({\d+})"))
                    {
                        tokens.Add(new HyperlinkToken(str));
                    }
                    else
                    {
                        tokens.Add(new Token(str));
                    }
                }
                return tokens;
            }
        }
    }
    

    然后在 XAML 中我这样使用它:

    <TextBlock x:Name="tblk_LogFileLink" TextWrapping="Wrap">
        <TextBlock.Tag>
            <MultiBinding Converter="{StaticResource TextBlockFormatToHyperlinkConverter}">
                <Binding x:Name="textblock" ElementName="tblk_LogFileLink"/>
                <Binding x:Name="formatString" Source="Click to open the {0}."/>
                <Binding x:Name="firstHyperlink">
                    <Binding.Source>
                        <Hyperlink NavigateUri="{Binding LogPath}">
                            <Run Text="{x:Static localization:Resources.LBL_LOG_FILE}"/>
                        </Hyperlink>
                    </Binding.Source>
                </Binding>
            </MultiBinding>
        </TextBlock.Tag>
    </TextBlock>
    

    如果您的字符串格式需要更多,您可以向 MultiBinding 添加多个超链接。

    这让我可以本地化整个字符串,同时仍然提供超链接文本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-11
      • 2012-12-07
      • 1970-01-01
      • 2011-08-10
      • 2023-01-26
      • 2011-08-22
      • 2014-11-07
      相关资源
      最近更新 更多