简体   繁体   English

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

[英]Create Hyperlink in TextBlock via Binding

My problem is to find the urls from the text content and convert it into the clickable hyperlinks via data binding.我的问题是从文本内容中找到 url,并通过数据绑定将其转换为可点击的超链接。

This is what I've tried这是我试过的

 <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>

In code,在代码中,

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;
        }
}
}

The output should be something like this输出应该是这样的

<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>

Any Help?任何帮助?

To do what you want you will have to use Inlines property of your TextBlock , but as it's not a DependencyProperty , it cannot be a target of binding.要执行您想要的操作,您必须使用TextBlock 的Inlines属性,但由于它不是DependencyProperty ,因此不能成为绑定目标。 We will have to extend your TextBlock class, but as it's sealed we will have to use other class.我们将不得不扩展您的TextBlock类,但由于它是密封的,我们将不得不使用其他类。

Lets define static class, which will add apropriate Inline - Hyperlink or Run , depending on Regex match.让我们定义静态类,它将根据正则表达式匹配添加适当的内联- HyperlinkRun It can look for example like this:它可以看起来像这样:

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);
                    }                        
            }
        }));
}

Then in XAML we use it just like this:然后在 XAML 中我们像这样使用它:

<TextBlock local:TextBlockExtension.FormattedText="{Binding MyText}" FontSize="15"/>

And after putting some text to my property:在将一些文本放入我的财产后:

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

I can see such a result:我可以看到这样的结果:

样品链接

I stumbled on this post while looking for the same for UWP .我在为UWP寻找相同内容时偶然发现了这篇文章。 In case you are here too for the same, I'd recommend you use a HyperlinkButton instead of a Hyperlink wrapped in a Textblock .如果您也在这里,我建议您使用HyperlinkButton而不是包裹在Textblock中的Hyperlink Below is the code on how to use it.下面是关于如何使用它的代码。

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

You can also use Binding instead of x:Bind and yes you can set the Mode=OneWay too.您也可以使用Binding而不是x:Bind是的,您也可以设置Mode=OneWay

Read More on Microsoft Docs 阅读有关 Microsoft Docs 的更多信息

You can't put Hyperlink objects inside a String.您不能将超链接对象放在字符串中。 Instead you need to return a Span containing inlines from your converter.相反,您需要从转换器返回一个包含内联的 Span。 The plain text will be Run objects and the links will be Hyperlink objects.纯文本将是运行对象,链接将是超链接对象。

    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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM