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>
私は次のエラーが発生しています:
プロパティ「テキスト」は、タイプ「ハイパーリンク」の値をサポートしていません。
何が間違っていますか?
アプリケーションで web browser でリンクを開くには、プログラムで機能する関数に RequestNavigate イベントを設定して HyperLink を追加する必要がありますパラメーターとしてアドレスを使用してWebブラウザーを開きます。
<TextBlock>
<Hyperlink NavigateUri="http://www.google.com" RequestNavigate="Hyperlink_RequestNavigate">
Click here
</Hyperlink>
</TextBlock>
コードビハインドでは、RequestNavigateイベントを処理するために、これに似た何かを追加する必要があります。
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}
さらに、次のインポートも必要です。
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="http://stackoverflow.com" custom::HyperlinkExtensions.IsExternal="true">
Click here
</Hyperlink>
</TextBlock>
Hyperlink
はnotコントロールであり、 フローコンテンツ 要素です。フローコンテンツをサポートするコントロールでのみ使用できます。 TextBlock
のように。 TextBoxes
はプレーンテキストのみです。
後で文字列をローカライズする場合、それらの答えでは不十分です。次のようなものをお勧めします。
<TextBlock>
<Hyperlink NavigateUri="http://labsii.com/">
<Hyperlink.Inlines>
<Run Text="Click here"/>
</Hyperlink.Inlines>
</Hyperlink>
</TextBlock>
私見の最も簡単な方法は、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;
}
}
また、Hyperlink
をナビゲーションに使用する必要がないことに注意してください。コマンドに接続できます。
例えば:
<TextBlock>
<Hyperlink Command="{Binding ClearCommand}">Clear</Hyperlink>
</TextBlock>
再利用可能なハンドラーというアーサーのアイデアは好きでしたが、もっと簡単な方法があると思います。
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
if (sender.GetType() != typeof (Hyperlink))
return;
string link = ((Hyperlink) sender).NavigateUri.ToString();
Process.Start(link);
}
明らかに、あらゆる種類のプロセスを開始するとセキュリティ上のリスクが生じる可能性があるため、注意してください。
これが誰かにも役立つことを願っています。
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();
}
}
}
私の意見で最も美しい方法の1つは(現在一般的に利用可能になっているため)、動作を使用することです。
以下が必要です。
Microsoft.Xaml.Behaviors.Wpf
xamlコード:
xmlns:Interactions="http://schemas.Microsoft.com/xaml/behaviors"
そして
<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>
動作コード:
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();
}
}
}