Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class HighlightingHyperlinksTextBlockBehavior : Behavior<TextBlock>
- {
- // Это свойство зависимости, в которое будем помещать входную строку
- public string Text
- {
- get => (string)GetValue(TextProperty);
- set => SetValue(TextProperty, value);
- }
- public static readonly DependencyProperty TextProperty =
- DependencyProperty.Register(nameof(Text), typeof(string),
- typeof(HighlightingHyperlinksTextBlockBehavior), new PropertyMetadata("", TextPropertyChangedCallback));
- // Этот метод будет вызываться при изменении свойства Text
- static void TextPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- var behavior = (HighlightingHyperlinksTextBlockBehavior)d;
- if (behavior.AssociatedObject == null) return;
- // Отписываем все существующие "старые" Hyperlink от RequestNavigate
- foreach (var hlink in behavior.AssociatedObject.Inlines.OfType<Hyperlink>())
- hlink.RequestNavigate -= OnRequestNavigate;
- // Очищаем у связанного TextBox коллекцию Inline'ов
- behavior.AssociatedObject.Inlines.Clear();
- // Преобразуем символы nr в реальные переводы строк
- var text = Regex.Unescape((string)e.NewValue ?? "");
- // Шаблон для Url
- var pattern = @"(http|ftp|https)://([w_-]+(?:(?:.[w_-]+)+))([w.,@?^=%&:/~+#-]*[w@?^=%&/~+#-])?";
- // Ищем все Url во входной строке и собираем из них Hyperlink'и
- var hlinkParts =
- Regex.Matches(text, pattern)
- .OfType<Match>()
- .Select(m => m.Value)
- .Select(s => new Hyperlink(new Run(s)) { NavigateUri = new Uri(s) })
- .ToArray();
- // Остальные куски текста (которые не входят в Url) просто помещаем в Run'ы
- var runParts =
- Regex.Split(text, pattern, RegexOptions.ExplicitCapture)
- .Select(s => new Run(s))
- .ToArray();
- for (int i = 0; i < hlinkParts.Length + runParts.Length; ++i)
- // И добавляем в нее по очереди Run и Hyperlink
- behavior.AssociatedObject.Inlines.Add(i % 2 == 0 ? runParts[i / 2] : (Inline)hlinkParts[i / 2]);
- // Подписываем все "новые" Hyperlink на RequestNavigate
- foreach (var hlink in hlinkParts)
- hlink.RequestNavigate += OnRequestNavigate;
- }
- static void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
- {
- Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
- e.Handled = true;
- }
- }
- <TextBlock xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
- <i:Interaction.Behaviors>
- <local:HighlightingHyperlinksTextBlockBehavior Text="{Binding Text}"/>
- </i:Interaction.Behaviors>
- </TextBlock>
Add Comment
Please, Sign In to add comment