在WPF应用程序中,如何使FlowDocument超链接启动浏览器并跳转到URL?

14

以下的WPF应用程序代码创建了一个看起来和行为像超链接的超链接,但是当单击时不会执行任何操作

我需要做出什么样的更改才能在单击它时打开默认浏览器并跳转到指定的 URL?

alt text http://www.deviantsart.com/upload/4fbnq2.png

XAML:

<Window x:Class="TestLink238492.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel Margin="10">
        <ContentControl x:Name="MainArea"/>
    </StackPanel>
</Window>

后台代码:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace TestLink238492
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            FlowDocumentScrollViewer fdsv = new FlowDocumentScrollViewer();

            FlowDocument doc = new FlowDocument();
            fdsv.Document = doc;
            fdsv.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
            doc.PagePadding = new Thickness(0);
            Paragraph paragraph = new Paragraph();
            doc.Blocks.Add(paragraph);

            Run run = new Run("this is flow document text and ");
            paragraph.Inlines.Add(run);

            Run run2 = new Run("this is a hyperlink");
            Hyperlink hlink = new Hyperlink(run2);
            hlink.NavigateUri = new Uri("http://www.google.com");
            paragraph.Inlines.Add(hlink);

            StackPanel sp = new StackPanel();
            TextBlock tb = new TextBlock();
            tb.Text = "this is textblock text";
            sp.Children.Add(tb);
            sp.Children.Add(fdsv);

            MainArea.Content = sp;
        }
    }
}

请参见后续的https://dev59.com/GWkv5IYBdhLWcg3w8FWY - 这两个问题可能应该合并,但我不确定它们是否是真正的重复。 - GS - Apologise to Monica
3个回答

18
我找到了答案,你需要添加RequestNavigate并自己处理:
Run run2 = new Run("this is a hyperlink");
Hyperlink hlink = new Hyperlink(run2);
hlink.NavigateUri = new Uri("http://www.google.com");
hlink.RequestNavigate += new System.Windows.Navigation.RequestNavigateEventHandler(hlink_RequestNavigate);
paragraph.Inlines.Add(hlink);


void hlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
    Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
    e.Handled = true;
}

1
如果我从RTF加载文档会怎样? - Poma

12

我得到了这个Poma的解决方案。下面的代码部分应该添加到您需要执行此操作的类中。或者,如果您需要从多个文件中访问它,可以将其放在某个静态类中。我稍微调整了一下以适应我的情况。

    #region Activate Hyperlinks in the Rich Text box
    //https://dev59.com/bVXTa4cB1Zd3GeqP3qr6
    void SubscribeToAllHyperlinks(FlowDocument flowDocument)
    {
        var hyperlinks = GetVisuals(flowDocument).OfType<Hyperlink>();
        foreach (var link in hyperlinks)
            link.RequestNavigate += new System.Windows.Navigation.RequestNavigateEventHandler(link_RequestNavigate);
    }

    public static IEnumerable<DependencyObject> GetVisuals(DependencyObject root)
    {
        foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
        {
            yield return child;
            foreach (var descendants in GetVisuals(child))
                yield return descendants;
        }
    }

    void link_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
    {
        //https://dev59.com/LXE95IYBdhLWcg3wf98F
        Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
        e.Handled = true;
    }
    #endregion Activate Hyperlinks in the Rich Text box

你需要在代码中这样调用它:

        string xaml = HTMLConverter.HtmlToXamlConverter.ConvertHtmlToXaml(this.itemControl.NotificationItem.Body, true);
        FlowDocument flowDocument = XamlReader.Load(new XmlTextReader(new StringReader(xaml))) as FlowDocument;
        SubscribeToAllHyperlinks(flowDocument);
        bodyFlowDocument.Document = flowDocument;

所有的HTML转换器都可以在这里找到:http://blogs.msdn.com/b/wpfsdk/archive/2006/05/25/606317.aspx。如果您需要将HTML转换为Flow文档,则可以使用它。尽管如此,这略微超出了本主题的范围。


起初,这个解决方案对我没有用,所有的超链接都被禁用了。只有在我改变了SubscribeToAllHyperlinks并使用link.Command而不是事件处理程序之后,一切才顺利运行。我正在使用.Net 4.5,也许这会有所不同。 - Heinz Kessler

0
接受的答案对我来说并不完全适用。如this issue中所详细说明的那样,需要包含UseShellExecute = true。因此,RequestNavigateEventHandler将如下所示:
void hlink_RequestNavigate(object sender, RequestNavigateEventArgs e) {
    var sInfo = new System.Diagnostics.ProcessStartInfo(e.Uri.AbsoluteUri);
    sInfo.UseShellExecute = true;
    System.Diagnostics.Process.Start(sInfo);
    e.Handled = true;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接