C# 在WPF中使用超链接的示例
我看到了一些建议,您可以通过C# 在WPF中使用超链接的示例,c#,wpf,xaml,hyperlink,C#,Wpf,Xaml,Hyperlink,我看到了一些建议,您可以通过hyperlink控件向WPF应用程序添加超链接 以下是我如何在代码中使用它: <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/ex
hyperlink
控件向WPF应用程序添加超链接
以下是我如何在代码中使用它:
<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>
点击这里
我发现以下错误:
属性“Text”不支持“Hyperlink”类型的值
我做错了什么?
Hyperlink
不是一个控件,它是一个元素,您只能在支持流内容的控件中使用它,例如TextBlock
<代码>文本框只有纯文本。如果希望应用程序在中打开链接,则需要将事件集添加到以编程方式打开以地址作为参数的web浏览器的函数中
<TextBlock>
<Hyperlink NavigateUri="http://www.google.com" RequestNavigate="Hyperlink_RequestNavigate">
Click here
</Hyperlink>
</TextBlock>
此外,您还需要以下导入:
using System.Diagnostics;
using System.Windows.Navigation;
在您的应用程序中,它将如下所示:
除了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;
}
}
然后像这样使用它:
<TextBlock>
<Hyperlink NavigateUri="https://stackoverflow.com"
custom:HyperlinkExtensions.IsExternal="true">
Click here
</Hyperlink>
</TextBlock>
点击这里
我喜欢Arthur关于可重用处理程序的想法,但我认为有一种更简单的方法:
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
if (sender.GetType() != typeof (Hyperlink))
return;
string link = ((Hyperlink) sender).NavigateUri.ToString();
Process.Start(link);
}
显然,启动任何类型的进程都可能存在安全风险,因此请小心。IMHO最简单的方法是使用继承自
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;
}
}
//
///在默认系统浏览器中打开
///
公共类外部浏览器超链接:超链接
{
公共外部浏览器超链接()
{
RequestNavigate+=OnRequestNavigate;
}
私有void OnRequestNavigate(对象发送方,RequestNavigateEventArgs e)
{
Process.Start(新的ProcessStartInfo(e.Uri.AbsoluteUri));
e、 已处理=正确;
}
}
如果您想稍后对字符串进行本地化,那么这些答案还不够,我建议如下:
<TextBlock>
<Hyperlink NavigateUri="http://labsii.com/">
<Hyperlink.Inlines>
<Run Text="Click here"/>
</Hyperlink.Inlines>
</Hyperlink>
</TextBlock>
希望这对其他人也有帮助
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();
}
}
}
还请注意,
Hyperlink
不必用于导航。可以将其连接到命令
例如:
<TextBlock>
<Hyperlink Command="{Binding ClearCommand}">Clear</Hyperlink>
</TextBlock>
清楚的
在我看来,最美丽的方式之一(因为现在已经很普遍了)就是使用行为
它要求:
- nuget依赖项:
Microsoft.Xaml.Behaviors.Wpf
- 如果你已经有了内置的行为,你可能不得不在微软的博客上遵循这一点李>
xmlns:Interactions="http://schemas.microsoft.com/xaml/behaviors"
及
行为守则:
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();
}
}
}
使用System.Windows;
使用System.Windows.Documents;
使用System.Windows.Navigation;
使用Microsoft.Xaml.Behaviors;
名称空间YourNameSpace
{
公共类HyperlinkOpenBehavior:行为
{
公共静态只读DependencyProperty ConfirmNavigationProperty=DependencyProperty.Register(
nameof(ConfirmNavigation)、typeof(bool)、typeof(hyperlinkopenbehavior)、newpropertyMetadata(default(bool));
公共布尔确认导航
{
获取{return(bool)GetValue(ConfirmNavigationProperty);}
set{SetValue(ConfirmNavigationProperty,value);}
}
///
受保护的覆盖无效附加()
{
this.AssociatedObject.RequestNavigate+=NavigationRequested;
this.AssociatedObject.Unloaded+=AssociatedObjectOnUnloaded;
base.onatached();
}
私有无效关联的ObjectOnUnloaded(对象发送方,RoutedEventArgs e)
{
this.AssociatedObject.Unloaded-=AssociatedObjectOnUnloaded;
this.AssociatedObject.RequestNavigate-=NavigationRequested;
}
private void NavigationRequested(对象发送方,RequestNavigateEventArgs e)
{
如果(!ConfirmNavigation | | MessageBox.Show(“确定吗?”,“问题”,MessageBoxButton.YesNo,MessageBoxImage.Question)==MessageBoxResult.Yes)
{
OpenUrl();
}
e、 已处理=正确;
}
私有void OpenUrl()
{
//Process.Start(新的ProcessStartInfo(AssociatedObject.NavigateUri.AbsoluteUri));
Show($“打开{AssociatedObject.NavigateUri}”);
}
///
附加时受保护的覆盖无效()
{
this.AssociatedObject.RequestNavigate-=NavigationRequested;
base.OnDetaching();
}
}
}
我在这个问题中使用了答案,我对此有异议
它返回异常:{“系统找不到指定的文件。”}
经过一点调查。事实证明,如果WPF应用程序是核心,则需要将UseShellExecute
更改为true
Microsoft中提到了这一点:
如果在启动过程时应使用外壳,则为true;假若
进程应该直接从可执行文件创建。这个
在.NET Framework应用程序上默认为true,在.NET核心应用程序上默认为false
因此,要实现此功能,您需要添加UseShellExecute
,并将其设置为true
:
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri){ UseShellExecute = true });
谢谢,但是有没有办法通过绑定来指定链接文本(在本例中为“单击此处”)?只需在超链接中再次放置一个文本块并绑定Textproperty@Thomas-要执行命令,只需将必要的命令绑定到超链接的command属性。重要说明:您必须具有非空的NavigateUri或从不调用event RequestNavigate我必须这样做:Process.Start(new ProcessStartInfo
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();
}
}
}
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri){ UseShellExecute = true });