通过绑定在TextBlock中创建超链接

7
我的问题是从文本内容中找到URL并通过数据绑定将其转换为可点击的超链接。
这是我尝试过的方法。
 <TextBlock Tag="{Binding message}" x:Name="postDescription" TextWrapping="Wrap" 
  Grid.Row="3" Grid.ColumnSpan="3" Margin="10,10,10,12" FontSize="16" 
  TextAlignment="Justify" Foreground="{StaticResource foreGroundWhite}" >
    <Run Text="{Binding description, Converter={StaticResource statusFormatter}}" />
  </TextBlock>

在代码中,

public class StatusFormatter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return returnTextWithUrl((String)value);
        }

        public static String returnTextWithUrl(String text)
        {
            if(text == null) { return null;  }
            MatchCollection mactches = uriFindRegex.Matches(text);

            foreach (Match match in mactches)
            {
                //Need Help here
                HyperlinkButton hyperlink = new HyperlinkButton();
                hyperlink.Content = match.Value;
                hyperlink.NavigateUri = new Uri(match.Value);
                text = text.Replace(match.Value, ??);
            }
            return text;
        }
}
}

输出结果应该类似于这样。
<TextBlock Tag="{Binding message}" x:Name="postDescription" TextWrapping="Wrap" 
      Grid.Row="3" Grid.ColumnSpan="3" Margin="10,10,10,12" FontSize="16" 
      TextAlignment="Justify" Foreground="{StaticResource foreGroundWhite}" >
        Click this link -
        <Hyperlink NavigateUri="http://www.bing.com">bing</Hyperlink>
        - for more info.
      </TextBlock>

需要帮忙吗?

3个回答

14
要实现您想要的功能,您需要使用的属性,但由于它不是,因此不能成为绑定的目标。我们将不得不扩展您的类,但由于它是的,所以我们将不得不使用其他类。
让我们定义一个类,它将根据匹配添加适当的 - HyperlinkRun。它可以像这样:
public static class TextBlockExtension
{
    public static string GetFormattedText(DependencyObject obj)
    { return (string)obj.GetValue(FormattedTextProperty); }

    public static void SetFormattedText(DependencyObject obj, string value)
    { obj.SetValue(FormattedTextProperty, value); }

    public static readonly DependencyProperty FormattedTextProperty =
        DependencyProperty.Register("FormattedText", typeof(string), typeof(TextBlockExtension),
        new PropertyMetadata(string.Empty, (sender, e) =>
        {
            string text = e.NewValue as string;
            var textBl = sender as TextBlock;
            if (textBl != null)
            {
                textBl.Inlines.Clear();
                Regex regx = new Regex(@"(http://[^\s]+)", RegexOptions.IgnoreCase);
                var str = regx.Split(text);
                for (int i = 0; i < str.Length; i++)
                    if (i % 2 == 0)
                        textBl.Inlines.Add(new Run { Text = str[i] });
                    else
                    {
                        Hyperlink link = new Hyperlink { NavigateUri = new Uri(str[i]), Foreground = Application.Current.Resources["PhoneAccentBrush"] as SolidColorBrush };
                        link.Inlines.Add(new Run { Text = str[i] });
                        textBl.Inlines.Add(link);
                    }                        
            }
        }));
}

然后在XAML中我们就可以像这样使用它:
<TextBlock local:TextBlockExtension.FormattedText="{Binding MyText}" FontSize="15"/>

在将一些文本放入我的属性后:

private void firstBtn_Click(object sender, RoutedEventArgs e)
{
    MyText = @"Simple text with http://mywebsite.com link";
}

我能看到这样的结果:

SampleLink


我遇到了一个异常,DependencyProperty TextBlockExtension。无法在类型为System.Windows.Controls.TextBlock的对象上设置FormattedText,有什么想法吗? - esskar
@esskar 你是针对 Runtime 还是 Silverlight 开发的? - Romasz
@esskar,在Silverlight中,至少使用上述代码不起作用。我现在没有解决方案,所以很遗憾无法帮助你。 - Romasz
1
你节省了我几个小时的时间...非常感谢。解决了我的通用Windows手机应用程序问题。 - jamdownian
2
已经过去了一年,但我将 DependencyProperty.Register 更改为 DependencyProperty.RegisterAttached 以使其作为附加属性工作。 - kurakura88
显示剩余9条评论

1

我在寻找有关 UWP 的相同内容时偶然发现了这篇文章。如果您也是为了同样的原因而来,请使用 HyperlinkButton 而不是包含在 Textblock 中的 Hyperlink。以下是如何使用它的代码。

<HyperlinkButton Content="{x:Bind Text}" NavigateUri="{x:Bind Hyperlink}"/>

你也可以使用 Binding 而不是 x:Bind,并且可以设置 Mode=OneWay

在 Microsoft Docs 上阅读更多


-1

您不能将超链接对象放在字符串中。相反,您需要返回一个包含转换器中行内元素的 Span。纯文本将是 Run 对象,而链接将是 Hyperlink 对象。

    public static Span returnTextWithUrl(String text)
    {
        if(text == null) { return null;  }
        var span = new Span();
        MatchCollection mactches = uriFindRegex.Matches(text);
        int lastIndex = 0;
        foreach (Match match in mactches)
        {
            var run = new Run(text.Substring(lastIndex, match.Index - lastIndex));
            span.Inlines.Add(run);
            lastIndex = match.Index + match.Length;
            var hyperlink = new Hyperlink();
            hyperlink.Content = match.Value;
            hyperlink.NavigateUri = new Uri(match.Value);
            span.Inlines.Add(hyperlink);
        }
        span.Inlines.Add(new Run(text.Substring(lastIndex)));
        return span;
    }

似乎我无法在WinRT中将span绑定到Run文本属性。它会将内容显示为Windows.UI.Xaml.Documents.Span。还有其他方法可以实现吗? - MohanRajNK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接