WPF - Making hyperlinks clickable

后端 未结 5 930
清歌不尽
清歌不尽 2020-11-28 06:35

I\'ve got a bit of text that I\'m trying to display in a list. Some of those pieces of a text contain a hyperlink. I\'d like to make the links clickable within the text.

5条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-28 06:43

    The VB.Net version of Bojan's answer. I improved a little upon it: This code will parse an url like http://support.mycompany.com?username=x&password=y to an inline of http://support.mycompany.com, while still navigating to the full url with username and password

    Imports System.Text.RegularExpressions
    Imports System.Windows
    Imports System.Windows.Controls
    Imports System.Windows.Documents
    
    Public Class NavigationService
        ' Copied from http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx '
        Private Shared ReadOnly RE_URL = New Regex("(?#Protocol)(?(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2})))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?")
    
        Public Shared ReadOnly TextProperty = DependencyProperty.RegisterAttached( _
            "Text",
            GetType(String),
            GetType(NavigationService),
            New PropertyMetadata(Nothing, AddressOf OnTextChanged)
        )
    
        Public Shared Function GetText(d As DependencyObject) As String
            Return TryCast(d.GetValue(TextProperty), String)
        End Function
    
        Public Shared Sub SetText(d As DependencyObject, value As String)
            d.SetValue(TextProperty, value)
        End Sub
    
        Private Shared Sub OnTextChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
            Dim text_block = TryCast(d, TextBlock)
            If text_block Is Nothing Then Return
    
            text_block.Inlines.Clear()
    
            Dim new_text = CStr(e.NewValue)
            If String.IsNullOrEmpty(new_text) Then Return
    
            ' Find all URLs using a regular expression '
            Dim last_pos As Integer = 0
            For Each match As Match In RE_URL.Matches(new_text)
                'Copy raw string from the last position up to the match '
                If match.Index <> last_pos Then
                    Dim raw_text = new_text.Substring(last_pos, match.Index - last_pos)
                    text_block.Inlines.Add(New Run(raw_text))
                End If
    
                ' Create a hyperlink for the match '
                Dim link = New Hyperlink(New Run(match.Groups("domainURL").Value)) With
                    {
                        .NavigateUri = New Uri(match.Value)
                    }
                AddHandler link.Click, AddressOf OnUrlClick
    
                text_block.Inlines.Add(link)
    
                'Update the last matched position '
                last_pos = match.Index + match.Length
            Next
    
            ' Finally, copy the remainder of the string '
            If last_pos < new_text.Length Then
                text_block.Inlines.Add(New Run(new_text.Substring(last_pos)))
            End If
        End Sub
    
        Private Shared Sub OnUrlClick(sender As Object, e As RoutedEventArgs)
            Try
                Dim link = CType(sender, Hyperlink)
                Process.Start(link.NavigateUri.ToString)
            Catch
            End Try
        End Sub
    End Class
    

提交回复
热议问题