WPF'de Köprü kullanılan örnek


160

HyperlinkKontrol yoluyla WPF uygulamasına köprü ekleyebileceğiniz birkaç öneri gördüm .

İşte benim kodda kullanmaya çalışıyorum:

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

Aşağıdaki hatayı alıyorum:

'Metin' özelliği, 'Köprü' türündeki değerleri desteklemez.

Neyi yanlış yapıyorum?

Yanıtlar:


331

Uygulamanızın bağlantıyı bir web tarayıcısında açmasını istiyorsanız , RequestNavigate olayı ayarlanmış bir programa adresli bir web tarayıcısını parametre olarak açan bir işleve bir HyperLink eklemeniz gerekir .

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

Arkadaki kodda, RequestNavigate olayını işlemek için buna benzer bir şey eklemeniz gerekir.

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
    Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
    e.Handled = true;
}

Ayrıca aşağıdaki ithalatlara da ihtiyacınız olacak.

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

Uygulamanızda böyle görünecektir.

oO


6
Not: RequestNavigateEventArgsiçindedir System.Windows.Navigationad.
Ben

2
Teşekkürler, ancak bağlantı metnini (bu örnekte "burayı tıklayın") bağlayıcı olarak belirtmenin herhangi bir yolu var mı?
Agent007

6
Köprü içine tekrar bir Textblock koyun ve TextProperty'yi bağlayın
KroaX

2
Not # 2: Processve ProcessStartInfoher ikisi de System.Diagnosticsad alanındadır.
user2023861

3
Önemli not : boş olmayan bir NavigateUri'ye sahip olmanız veya RequestNavigate etkinliğinin asla çağrılmaması gerekir
MuiBienCarlota

60

Fuji'nin yanıtına ek olarak, işleyiciyi ekli bir mülke dönüştürerek tekrar kullanılabilir hale getirebiliriz:

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

Ve şu şekilde kullanın:

<TextBlock>
<Hyperlink NavigateUri="http://stackoverflow.com" custom::HyperlinkExtensions.IsExternal="true">
       Click here
    </Hyperlink>
 </TextBlock>

Zarif çözüm. Teşekkür ederim
Jeson Martajaya

30

Hyperlinkolduğu değil bir kontrol, bir olan akış içeriği eleman, yalnızca gibi kontrollerde hangi destek akış içeriği kullanabilirsiniz TextBlock. TextBoxessadece düz metin var.


26

Dizeyi daha sonra yerelleştirmek istiyorsanız, o zaman bu cevaplar yeterli değildir, şöyle bir şey öneririm:

<TextBlock>
    <Hyperlink NavigateUri="http://labsii.com/">
       <Hyperlink.Inlines>
            <Run Text="Click here"/>
       </Hyperlink.Inlines>
   </Hyperlink>
</TextBlock>

21

IMHO en basit yolu, miras alınan yeni kontrolü kullanmaktır 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;
    }
}

16

Bunun Hyperlinknavigasyon için kullanılması gerekmediğine de dikkat edin . Bir komuta bağlayabilirsiniz.

Örneğin:

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

16

Bu sorunun cevabını kullandım ve bununla ilgili bir sorunum var.

İstisna döndürür: {"The system cannot find the file specified."}

Biraz araştırmadan sonra. Bu sizin WPF uygulama .CORE ise vermeniz gereken çıkıyor UseShellExecuteiçin true.

Microsoft belgelerinde bu belirtilmiştir :

işlemi başlatırken kabuk kullanılması gerekiyorsa true; işlemin doğrudan yürütülebilir dosyadan oluşturulması gerekiyorsa false. Varsayılan, .NET Framework uygulamalarında doğrudur ve .NET Core uygulamalarında yanlıştır.

Bu yüzden bu işi yapmak için şunları eklemeniz UseShellExecutegerekir true:

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

Aynı sorunu yaşadım ve nasıl düzeltileceğini görmek için buraya geldim, ancak neden hala UseShelExecute = trueherhangi bir fikre devam ediyor ?
Yüksek Ovalar Grifter

@HighPlainsGrifter sadece UseShelExecute = true yaptık ama yine de aynı sorunu var anlamak için? Bu durumda görsel stüdyoyu yönetici modunda çalıştırmayı deneyin (yönetici olarak çalıştırın) Bu işlemin yönetici ayrıcalığı gerektiren kaynaklara erişmesi gerektiğini düşünüyorum. Ve bu gerçek şey sadece .core projeleri için geçerlidir. cevabımı güncelleyebilmem için bana yardımcı olup olmadığını bildirin.
maytham-ɯɐɥʇʎɐɯ

Evet, yönetici kullanıcı olarak çalışıyorum Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });ve "System.ComponentModel.Win32Exception: '' Belirtilen dosyayı bulamıyorum '' hatasını alıyorum
High Plains Grifter

@HighPlainsGrifter ne olabilir başka emin değilim, eğer kaynak kodu varsa hata ayıklama için biraz zaman harcamak için welling ama herhangi bir şey söz vermeyeceğim. :)
maytham-ɯɐɥʇʎɐɯ

Ne yazık ki paylaşılabilir bir kod değil - Projeyi kaldırmak yerine şimdilik bir köprü kullanmak zorunda kaldım. Yine de teşekkürler.
Yüksek Ovalar Grifter

4

Arthur'un yeniden kullanılabilir bir işleyici fikrini beğendim, ancak bence bunu yapmanın daha basit bir yolu var:

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

Açıkçası, her türlü işleme başlamada güvenlik riskleri olabilir, bu yüzden dikkatli olun.


1

Umarım bu da birine yardım eder.

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

0

Bence en güzel yollardan biri (artık yaygın olarak mevcut olduğu için) davranışları kullanmak.

Gerektirir:

  • nuget bağımlılığı: Microsoft.Xaml.Behaviors.Wpf
  • zaten yerleşik davranışlarınız varsa , Microsofts blogunda bu kılavuzu takip etmeniz gerekebilir .

xaml kodu:

xmlns:Interactions="http://schemas.microsoft.com/xaml/behaviors"

VE

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

davranış kodu:

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();
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.