C# 在 WPF 中使用超链接的示例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10238694/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Example using Hyperlink in WPF
提问by Arsen Zahray
I've seen several suggestions, that you can add hyperlink to WPF application through Hyperlinkcontrol.
我看到了一些建议,您可以通过Hyperlink控件向 WPF 应用程序添加超链接。
Here's how I'm trying to use it in my code:
这是我尝试在我的代码中使用它的方式:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="BookmarkWizV2.InfoPanels.Windows.UrlProperties"
Title="UrlProperties" Height="754" Width="576">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid>
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" Grid.RowSpan="2">
<StackPanel >
<DockPanel LastChildFill="True" Margin="0,5">
<TextBlock Text="Url:" Margin="5"
DockPanel.Dock="Left" VerticalAlignment="Center"/>
<TextBox Width="Auto">
<Hyperlink NavigateUri="http://www.google.co.in">
Click here
</Hyperlink>
</TextBox>
</DockPanel >
</StackPanel>
</ScrollViewer>
</Grid>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Margin="0,7,2,7" Grid.Row="1" >
<Button Margin="0,0,10,0">
<TextBlock Text="Accept" Margin="15,3" />
</Button>
<Button Margin="0,0,10,0">
<TextBlock Text="Cancel" Margin="15,3" />
</Button>
</StackPanel>
</Grid>
</Window>
I'm getting following error:
我收到以下错误:
Property 'Text' does not support values of type 'Hyperlink'.
属性“文本”不支持“超链接”类型的值。
What am I doing wrong?
我究竟做错了什么?
采纳答案by eandersson
If you want your application to open the link in a web browseryou need to add a HyperLinkwith the RequestNavigateevent set to a function that programmatically opens a web-browser with the address as a parameter.
如果您希望您的应用程序在Web 浏览器中打开链接,您需要添加一个HyperLink,其中RequestNavigate事件设置为一个函数,该函数以编程方式打开一个以地址为参数的 Web 浏览器。
<TextBlock>
<Hyperlink NavigateUri="http://www.google.com" RequestNavigate="Hyperlink_RequestNavigate">
Click here
</Hyperlink>
</TextBlock>
In the code-behind you would need to add something similar to this to handle the RequestNavigate event.
在代码隐藏中,您需要添加与此类似的内容来处理 RequestNavigate 事件。
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
In addition you will also need the following imports.
此外,您还需要以下导入。
using System.Diagnostics;
using System.Windows.Navigation;
It would look like this in your application.
它在您的应用程序中看起来像这样。


回答by H.B.
Hyperlinkis nota control, it is a flow contentelement, you can only use it in controls which support flow content, like a TextBlock. TextBoxesonly have plain text.
Hyperlink是不是一个控制,它是一个流内容元素,你只能用它控制哪些支持流的内容,就像一个TextBlock。TextBoxes只有纯文本。
回答by Arthur Nunes
In addition to Fuji's response, we can make the handler reusable turning it into an attached property:
除了 Fuji 的响应之外,我们还可以使处理程序可重用,将其转换为附加属性:
public static class HyperlinkExtensions
{
public static bool GetIsExternal(DependencyObject obj)
{
return (bool)obj.GetValue(IsExternalProperty);
}
public static void SetIsExternal(DependencyObject obj, bool value)
{
obj.SetValue(IsExternalProperty, value);
}
public static readonly DependencyProperty IsExternalProperty =
DependencyProperty.RegisterAttached("IsExternal", typeof(bool), typeof(HyperlinkExtensions), new UIPropertyMetadata(false, OnIsExternalChanged));
private static void OnIsExternalChanged(object sender, DependencyPropertyChangedEventArgs args)
{
var hyperlink = sender as Hyperlink;
if ((bool)args.NewValue)
hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
else
hyperlink.RequestNavigate -= Hyperlink_RequestNavigate;
}
private static void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
}
And use it like this:
并像这样使用它:
<TextBlock>
<Hyperlink NavigateUri="http://stackoverflow.com" custom::HyperlinkExtensions.IsExternal="true">
Click here
</Hyperlink>
</TextBlock>
回答by Grant
I liked Arthur's idea of a reusable handler, but I think there's a simpler way to do it:
我喜欢 Arthur 的可重用处理程序的想法,但我认为有一种更简单的方法来做到这一点:
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
if (sender.GetType() != typeof (Hyperlink))
return;
string link = ((Hyperlink) sender).NavigateUri.ToString();
Process.Start(link);
}
Obviously there could be security risks with starting any kind of process, so be carefull.
显然,启动任何类型的过程都可能存在安全风险,所以要小心。
回答by Lu55
IMHO the simplest way is to use new control inherited from Hyperlink:
恕我直言,最简单的方法是使用继承自的新控件Hyperlink:
/// <summary>
/// Opens <see cref="Hyperlink.NavigateUri"/> in a default system browser
/// </summary>
public class ExternalBrowserHyperlink : Hyperlink
{
public ExternalBrowserHyperlink()
{
RequestNavigate += OnRequestNavigate;
}
private void OnRequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
}
回答by Ivan I?in
If you want to localize string later, then those answers aren't enough, I would suggest something like:
如果您想稍后本地化字符串,那么这些答案还不够,我建议如下:
<TextBlock>
<Hyperlink NavigateUri="http://labsii.com/">
<Hyperlink.Inlines>
<Run Text="Click here"/>
</Hyperlink.Inlines>
</Hyperlink>
</TextBlock>
回答by jaysonragasa
Hope this help someone as well.
希望这也能帮助别人。
using System.Diagnostics;
using System.Windows.Documents;
namespace Helpers.Controls
{
public class HyperlinkEx : Hyperlink
{
protected override void OnClick()
{
base.OnClick();
Process p = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = this.NavigateUri.AbsoluteUri
}
};
p.Start();
}
}
}
回答by Drew Noakes
Note too that Hyperlinkdoes not have to be used for navigation. You can connect it to a command.
还要注意,Hyperlink不必用于导航。您可以将其连接到命令。
For example:
例如:
<TextBlock>
<Hyperlink Command="{Binding ClearCommand}">Clear</Hyperlink>
</TextBlock>
回答by Dbl
One of the most beautiful ways in my opinion (since it is now commonly available) is using behaviours.
在我看来,最漂亮的方法之一(因为它现在普遍可用)是使用行为。
It requires:
这个需要:
- nuget dependency:
Microsoft.Xaml.Behaviors.Wpf - if you already have behaviours built in you might have to follow this guideon Microsofts blog.
- nuget 依赖:
Microsoft.Xaml.Behaviors.Wpf - 如果您已经内置了行为,则可能必须遵循Microsoft 博客上的本指南。
xaml code:
xml代码:
xmlns:Interactions="http://schemas.microsoft.com/xaml/behaviors"
AND
和
<Hyperlink NavigateUri="{Binding Path=Link}">
<Interactions:Interaction.Behaviors>
<behaviours:HyperlinkOpenBehaviour ConfirmNavigation="True"/>
</Interactions:Interaction.Behaviors>
<Hyperlink.Inlines>
<Run Text="{Binding Path=Link}"/>
</Hyperlink.Inlines>
</Hyperlink>
behaviour code:
行为代码:
using System.Windows;
using System.Windows.Documents;
using System.Windows.Navigation;
using Microsoft.Xaml.Behaviors;
namespace YourNameSpace
{
public class HyperlinkOpenBehaviour : Behavior<Hyperlink>
{
public static readonly DependencyProperty ConfirmNavigationProperty = DependencyProperty.Register(
nameof(ConfirmNavigation), typeof(bool), typeof(HyperlinkOpenBehaviour), new PropertyMetadata(default(bool)));
public bool ConfirmNavigation
{
get { return (bool) GetValue(ConfirmNavigationProperty); }
set { SetValue(ConfirmNavigationProperty, value); }
}
/// <inheritdoc />
protected override void OnAttached()
{
this.AssociatedObject.RequestNavigate += NavigationRequested;
this.AssociatedObject.Unloaded += AssociatedObjectOnUnloaded;
base.OnAttached();
}
private void AssociatedObjectOnUnloaded(object sender, RoutedEventArgs e)
{
this.AssociatedObject.Unloaded -= AssociatedObjectOnUnloaded;
this.AssociatedObject.RequestNavigate -= NavigationRequested;
}
private void NavigationRequested(object sender, RequestNavigateEventArgs e)
{
if (!ConfirmNavigation || MessageBox.Show("Are you sure?", "Question", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
OpenUrl();
}
e.Handled = true;
}
private void OpenUrl()
{
// Process.Start(new ProcessStartInfo(AssociatedObject.NavigateUri.AbsoluteUri));
MessageBox.Show($"Opening {AssociatedObject.NavigateUri}");
}
/// <inheritdoc />
protected override void OnDetaching()
{
this.AssociatedObject.RequestNavigate -= NavigationRequested;
base.OnDetaching();
}
}
}
回答by maytham-???????
I used the answer in this question and I got issue with it.
我在这个问题中使用了答案,但遇到了问题。
It return exception: {"The system cannot find the file specified."}
它返回异常: {"The system cannot find the file specified."}
After a bit of investigation. It turns out that if your WPF application is .CORE you need to make UseShellExecuteto true.
经过一番调查。事实证明,如果您的 WPF 应用程序是 .CORE,您需要UseShellExecute将true.
This is mentioned in Microsoft docs:
Microsoft文档中提到了这一点:
true if the shell should be used when starting the process; false if the process should be created directly from the executable file. The default is true on .NET Framework apps and false on .NET Core apps.
如果在启动进程时应该使用 shell,则为 true;如果进程应该直接从可执行文件创建,则为 false。.NET Framework 应用程序的默认值为 true,.NET Core 应用程序的默认值为 false。
So to make this work you need to added UseShellExecuteto true:
因此,要完成这项工作,您需要添加UseShellExecute到true:
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri){ UseShellExecute = true });

