Guest User

Untitled

a guest
Apr 22nd, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.07 KB | None | 0 0
  1. class HighlightingHyperlinksTextBlockBehavior : Behavior<TextBlock>
  2. {
  3. // Это свойство зависимости, в которое будем помещать входную строку
  4. public string Text
  5. {
  6. get => (string)GetValue(TextProperty);
  7. set => SetValue(TextProperty, value);
  8. }
  9.  
  10. public static readonly DependencyProperty TextProperty =
  11. DependencyProperty.Register(nameof(Text), typeof(string),
  12. typeof(HighlightingHyperlinksTextBlockBehavior), new PropertyMetadata("", TextPropertyChangedCallback));
  13.  
  14. // Этот метод будет вызываться при изменении свойства Text
  15. static void TextPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  16. {
  17. var behavior = (HighlightingHyperlinksTextBlockBehavior)d;
  18. if (behavior.AssociatedObject == null) return;
  19.  
  20. // Отписываем все существующие "старые" Hyperlink от RequestNavigate
  21. foreach (var hlink in behavior.AssociatedObject.Inlines.OfType<Hyperlink>())
  22. hlink.RequestNavigate -= OnRequestNavigate;
  23. // Очищаем у связанного TextBox коллекцию Inline'ов
  24. behavior.AssociatedObject.Inlines.Clear();
  25.  
  26. // Преобразуем символы nr в реальные переводы строк
  27. var text = Regex.Unescape((string)e.NewValue ?? "");
  28. // Шаблон для Url
  29. var pattern = @"(http|ftp|https)://([w_-]+(?:(?:.[w_-]+)+))([w.,@?^=%&:/~+#-]*[w@?^=%&/~+#-])?";
  30. // Ищем все Url во входной строке и собираем из них Hyperlink'и
  31. var hlinkParts =
  32. Regex.Matches(text, pattern)
  33. .OfType<Match>()
  34. .Select(m => m.Value)
  35. .Select(s => new Hyperlink(new Run(s)) { NavigateUri = new Uri(s) })
  36. .ToArray();
  37. // Остальные куски текста (которые не входят в Url) просто помещаем в Run'ы
  38. var runParts =
  39. Regex.Split(text, pattern, RegexOptions.ExplicitCapture)
  40. .Select(s => new Run(s))
  41. .ToArray();
  42.  
  43. for (int i = 0; i < hlinkParts.Length + runParts.Length; ++i)
  44. // И добавляем в нее по очереди Run и Hyperlink
  45. behavior.AssociatedObject.Inlines.Add(i % 2 == 0 ? runParts[i / 2] : (Inline)hlinkParts[i / 2]);
  46.  
  47. // Подписываем все "новые" Hyperlink на RequestNavigate
  48. foreach (var hlink in hlinkParts)
  49. hlink.RequestNavigate += OnRequestNavigate;
  50. }
  51.  
  52. static void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
  53. {
  54. Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
  55. e.Handled = true;
  56. }
  57. }
  58.  
  59. <TextBlock xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
  60. <i:Interaction.Behaviors>
  61. <local:HighlightingHyperlinksTextBlockBehavior Text="{Binding Text}"/>
  62. </i:Interaction.Behaviors>
  63. </TextBlock>
Add Comment
Please, Sign In to add comment