Monk Asked:2020-04-30 23:11:45 +0000 UTC2020-04-30 23:11:45 +0000 UTC 2020-04-30 23:11:45 +0000 UTC 使文本中的链接可点击 772 我用ListView它来显示日志。有时日志中有链接(例如,“无效链接:http ://example.com/ ”),我只想点击它们,它们会在普通浏览器中打开。 这可以自动完成,还是必须手动解析并转换为 和 的Run组合Hyperlink? c# 2 个回答 Voted vlasovsv 2020-04-30T23:41:37Z2020-04-30T23:41:37Z 如果链接可以出现在日志中的任何位置,那么您可以编写一个正则表达式来提取所需的一个或多个链接。根据收到的信息形成一个表示模型。然后为将使用 HyperLink 的 ListView 元素编写一个模板。 Best Answer Monk 2020-05-01T14:48:20Z2020-05-01T14:48:20Z 使用此处的实现和此处的正则表达式(但是,我在模板中添加了逗号作为分隔符,不幸的是,它发生在日志中),我们得到了这样的实现。 public class TextBlockWithHyperlinks : TextBlock { private static readonly Regex HyperlinkRegex = new Regex(@"(https?|ftp):\/\/[^\s/$.?#].[^\s,]*"); static TextBlockWithHyperlinks() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBlockWithHyperlinks), new FrameworkPropertyMetadata(typeof(TextBlockWithHyperlinks))); } public TextBlockWithHyperlinks() { TargetUpdated += (s, args) => Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(ParseHyperlinks)); } private void ParseHyperlinks() { var style = HyperlinkStyle; var text = Text; var matches = HyperlinkRegex.Matches(text); if (matches.Count == 0) return; Inlines.Clear(); var lastIndex = 0; foreach (Match match in matches) { Inlines.Add(text.Substring(lastIndex, match.Index - lastIndex)); lastIndex = match.Index + match.Length; var run = new Run(match.Value) { Style = style }; run.MouseDown += RunOnMouseDown; Inlines.Add(run); } Inlines.Add(text.Substring(lastIndex)); } private void RunOnMouseDown(object sender, MouseButtonEventArgs args) { var run = sender as Run; if (run == null) return; OnHyperlinkPressed(new HyperlinkPressedEventArgs(run.Text)); } public event EventHandler<HyperlinkPressedEventArgs> HyperlinkPressed; public void OnHyperlinkPressed(HyperlinkPressedEventArgs args) { var handler = HyperlinkPressed; handler?.Invoke(this, args); } public static readonly DependencyProperty HyperlinkStyleProperty = DependencyProperty.Register("HyperlinkStyle", typeof(Style), typeof(TextBlockWithHyperlinks)); public Style HyperlinkStyle { get { return (Style)GetValue(HyperlinkStyleProperty); } set { SetValue(HyperlinkStyleProperty, value); } } } public class HyperlinkPressedEventArgs : EventArgs { public readonly Uri Hyperlink; public HyperlinkPressedEventArgs(Uri hyperlink) { Hyperlink = hyperlink; } public HyperlinkPressedEventArgs(string hyperlink) : this(new Uri(hyperlink)) { } } 它很容易插入到标记中,只有一个但是 - 你总是需要包含NotifyOnTargetUpdated. <local:TextBlockWithHyperlinks HyperlinkPressed="TextBlockWithLinks_OnHyperlinkPressed" HyperlinkStyle="{StaticResource HyperlinkStyle}" Text="{Binding FormattedMessage, NotifyOnTargetUpdated=True}"/> 样式简单,下划线和蓝色: <Style x:Key="HyperlinkStyle" TargetType="{x:Type Run}" > <Style.Setters> <Setter Property="Foreground" Value="Blue"/> </Style.Setters> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="TextDecorations" Value="Underline"/> <Setter Property="Cursor" Value="Hand"/> </Trigger> </Style.Triggers> </Style> 理论上,链接处理程序应该在防止危险操作的情况下完成,但现在是这样的: private void TextBlockWithLinks_OnHyperlinkPressed(object sender, HyperlinkPressedEventArgs args) { System.Diagnostics.Process.Start(args.Hyperlink.OriginalString); }
如果链接可以出现在日志中的任何位置,那么您可以编写一个正则表达式来提取所需的一个或多个链接。根据收到的信息形成一个表示模型。然后为将使用 HyperLink 的 ListView 元素编写一个模板。
使用此处的实现和此处的正则表达式(但是,我在模板中添加了逗号作为分隔符,不幸的是,它发生在日志中),我们得到了这样的实现。
它很容易插入到标记中,只有一个但是 - 你总是需要包含
NotifyOnTargetUpdated.样式简单,下划线和蓝色:
理论上,链接处理程序应该在防止危险操作的情况下完成,但现在是这样的: