【问题标题】:Create Hyperlink in TextBlock via Binding通过绑定在 TextBlock 中创建超链接
【发布时间】:2015-01-01 19:49:31
【问题描述】:

我的问题是从文本内容中找到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>

有什么帮助吗?

【问题讨论】:

    标签: c# xaml data-binding windows-phone-8.1 win-universal-app


    【解决方案1】:

    要做你想做的事,你必须使用 TextBlockInlines 属性,但因为它不是 DependencyProperty,所以不能绑定的目标。我们将不得不扩展您的 TextBlock 类,但由于它是密封的,我们将不得不使用其他类。

    让我们定义 static 类,它将添加适当的 Inline - HyperlinkRun,具体取决于 Regex 匹配。例如,它可能看起来像这样:

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

    我可以看到这样的结果:

    【讨论】:

    • 我得到一个例外,DependencyProperty TextBlockExtension。无法在 System.Windows.Controls.TextBlock 类型的对象上设置 FormattedText,有什么想法吗?
    • @esskar 你把它变成静态的了吗?您是否还在 xaml 中添加了命名空间?
    • @Romasz 是的,我也是非静态的。
    • 你为我节省了几个小时......谢谢。解决了我的 windows phone 通用应用程序的问题。
    • @AzazulHaq 已经一年了,但我将DependencyProperty.Register 更改为DependencyProperty.RegisterAttached 以使其作为附加属性工作。
    【解决方案2】:

    我在寻找 UWP 时偶然发现了这篇文章。如果您也在这里,我建议您使用HyperlinkButton 而不是包裹在Textblock 中的Hyperlink。下面是如何使用它的代码。

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

    您也可以使用Binding 代替x:Bind,是的,您也可以设置Mode=OneWay

    Read More on Microsoft Docs

    【讨论】:

      【解决方案3】:

      您不能将超链接对象放在字符串中。相反,您需要从转换器返回包含内联的 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;
          }
      

      【讨论】:

      • 似乎无法将 span 绑定到 WinRT 中的 Run text 属性。它将内容显示为 Windows.UI.Xaml.Documents.Span。还有其他方法可以实现吗?
      猜你喜欢
      • 1970-01-01
      • 2011-10-15
      • 2012-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-24
      • 2011-08-22
      • 1970-01-01
      相关资源
      最近更新 更多