programing

WPF에서의 하이퍼링크 사용 예시

showcode 2023. 4. 10. 22:28
반응형

WPF에서의 하이퍼링크 사용 예시

WPF 응용 프로그램에 하이퍼링크를 추가할 수 있는 몇 가지 제안을 보았습니다.Hyperlink통제.

코드로 사용하는 방법은 다음과 같습니다.

<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' 형식의 값을 지원하지 않습니다.

내가 뭘 잘못하고 있지?

응용 프로그램이 웹 브라우저에서 링크를 열도록 하려면 매개 변수로 주소를 사용하여 웹 브라우저를 프로그래밍 방식으로 여는 함수에 RequestNavigate 이벤트를 설정한 HyperLink를 추가해야 합니다.

<TextBlock>           
    <Hyperlink NavigateUri="http://www.google.com" RequestNavigate="Hyperlink_RequestNavigate">
        Click here
    </Hyperlink>
</TextBlock>

코드 배후에 RequestNavigate 이벤트를 처리하려면 다음과 같은 내용을 추가해야 합니다.

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
    // for .NET Core you need to add UseShellExecute = true
    // see https://learn.microsoft.com/dotnet/api/system.diagnostics.processstartinfo.useshellexecute#property-value
    Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
    e.Handled = true;
}

또한 다음과 같은 Import도 필요합니다.

using System.Diagnostics;
using System.Windows.Navigation;

어플리케이션에서는 다음과 같이 표시됩니다.

o

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>

나중에 문자열을 현지화하려면 이 답변만으로는 충분하지 않습니다.다음과 같은 것을 권장합니다.

<TextBlock>
    <Hyperlink NavigateUri="https://speechcentral.net/">
       <Hyperlink.Inlines>
            <Run Text="Click here"/>
       </Hyperlink.Inlines>
   </Hyperlink>
</TextBlock>

Hyperlink컨트롤이 아니라 흐름 콘텐츠 요소이며 흐름 콘텐츠를 지원하는 컨트롤에서만 사용할 수 있습니다.TextBlock.TextBoxes일반 텍스트만 있습니다.

주의해 주세요.Hyperlink를 항법용으로 사용할 필요는 없습니다.명령어에 연결할 수 있습니다.

예를 들어 다음과 같습니다.

<TextBlock>
  <Hyperlink Command="{Binding ClearCommand}">Clear</Hyperlink>
</TextBlock>

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;
    }
}

이 질문에 답을 썼는데 문제가 생겼어요.

예외 반환:{"The system cannot find the file specified."}

좀 더 조사해보니.WPF 어플리케이션이 CORE인 경우는, 이 설정을 변경할 필요가 있습니다.UseShellExecute로.true.

이것은, Microsoft 의 문서에 기재되어 있습니다.

프로세스를 시작할 때 셸을 사용해야 하는 경우 true, 실행 파일에서 직접 프로세스를 생성해야 하는 경우 false입니다.기본값은 true 입니다.NET Framework 앱 및 false on.NET Core 앱

따라서 이 작업을 수행하려면 다음과 같이 추가해야 합니다.UseShellExecute로 설정합니다.true:

Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri){ UseShellExecute = true });

재사용 가능한 핸들러에 대한 아더의 아이디어는 좋았지만, 더 간단한 방법이 있을 것 같습니다.

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
    if (sender.GetType() != typeof (Hyperlink))
        return;
    string link = ((Hyperlink) sender).NavigateUri.ToString();
    Process.Start(link);
}

모든 종류의 프로세스를 시작하면 보안상의 위험이 있을 수 있으므로 주의해 주십시오.

내 생각에 가장 아름다운 방법 중 하나는 행동을 사용하는 것이다.

필요한 것은 다음과 같습니다.

  • nuget 의존관계:Microsoft.Xaml.Behaviors.Wpf
  • 이미 기본 제공 행동이 있는 경우 Microsoft 블로그에 있는 이 가이드를 따라야 할 수 있습니다.

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();
        }
    }
}

이것도 누군가에게 도움이 되길 바랍니다.

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();
        }
    }
}

언급URL : https://stackoverflow.com/questions/10238694/example-using-hyperlink-in-wpf

반응형