2009-10-14 27 views

回答

6

拼单个词涉及实际创建更多内联元素,因此您不能只将一个字符串绑定到TextBlock的文本并执行此操作。

我在过去为此做了什么创建了一个TextBlock的子类,它具有我绑定到的自定义属性。当此属性被绑定时,我清除基本TextBlock的内联,然后使用算法分析创建普通运行,粗体,超链接等的新字符串值。

以下是我为实验性Twitter客户端编写的一些示例代码它会检测URL,电子邮件和@ pattern并为它们创建超链接。普通文本以正常运行方式内联:

[ContentProperty("StatusText")] 
public sealed class StatusTextBlock : TextBlock 
{ 
    #region Fields 

    public static readonly DependencyProperty StatusTextProperty = DependencyProperty.Register(
                        "StatusText", 
                          typeof(string), 
                        typeof(StatusTextBlock), 
                        new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None, StatusTextBlock.StatusTextPropertyChangedCallback, null)); 
    private static readonly Regex UriMatchingRegex = new Regex(@"(?<url>[a-zA-Z]+:\/\/[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5}(:[0-9]{1,5})?([a-zA-Z0-9_\-\.\~\%\+\?\=\&\;\|/]*)?)|(?<emailAddress>[^\s][email protected][a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5})|(?<toTwitterScreenName>\@[a-zA-Z0-9\-_]+)", RegexOptions.Compiled); 

    #endregion 

    #region Constructors 

    public StatusTextBlock() 
    { 
    } 

    #endregion 

    #region Type specific properties 

    public string StatusText 
    { 
     get 
     { 
      return (string)this.GetValue(StatusTextBlock.StatusTextProperty); 
     } 

     set 
     { 
      this.SetValue(StatusTextBlock.StatusTextProperty, value); 
     } 
    } 

    #endregion 

    #region Helper methods 

    internal static IEnumerable<Inline> GenerateInlinesFromRawEntryText(string entryText) 
    { 
     int startIndex = 0; 
     Match match = StatusTextBlock.UriMatchingRegex.Match(entryText); 

     while(match.Success) 
     { 
      if(startIndex != match.Index) 
      { 
       yield return new Run(StatusTextBlock.DecodeStatusEntryText(entryText.Substring(startIndex, match.Index - startIndex))); 
      } 

      Hyperlink hyperLink = new Hyperlink(new Run(match.Value)); 

      string uri = match.Value; 

      if(match.Groups["emailAddress"].Success) 
      { 
       uri = "mailto:" + uri; 
      } 
      else if(match.Groups["toTwitterScreenName"].Success) 
      { 
       uri = "http://twitter.com/" + uri.Substring(1); 
      } 

      hyperLink.NavigateUri = new Uri(uri); 

      yield return hyperLink; 

      startIndex = match.Index + match.Length; 

      match = match.NextMatch(); 
     } 

     if(startIndex != entryText.Length) 
     { 
      yield return new Run(StatusTextBlock.DecodeStatusEntryText(entryText.Substring(startIndex))); 
     } 
    } 

    internal static string DecodeStatusEntryText(string text) 
    { 
     return text.Replace("&gt;", ">").Replace("&lt;", "<"); 
    } 

    private static void StatusTextPropertyChangedCallback(DependencyObject target, DependencyPropertyChangedEventArgs eventArgs) 
    { 
     StatusTextBlock targetStatusEntryTextBlock = (StatusTextBlock)target; 

     targetStatusEntryTextBlock.Inlines.Clear(); 

     string newValue = eventArgs.NewValue as string; 

     if(newValue != null) 
     { 
      targetStatusEntryTextBlock.Inlines.AddRange(StatusTextBlock.GenerateInlinesFromRawEntryText(newValue)); 
     } 
    } 

    #endregion 
} 
+0

您是否可以使用此方法使文本颜色不同? – 2009-10-15 02:33:21

+0

当然,你只需将Run实例的Foreground属性设置为你想要的任何刷子。 – 2009-10-15 03:05:43

+0

你有没有试过一个文本框与相同的东西,文本框不具有内联属性,所以你必须去富文本框我想。 – 2009-10-15 03:44:49

相关问题