How to make a simple hyperlink in XAML?

2019-01-16 23:37发布

问题:

All I want to do is make a little hyperlink in XAML. I've tried everything. I give up.

What is the syntax for this?

<StackPanel Width="70" HorizontalAlignment="Center">

    <Hyperlink Click="buttonClose_Click" Cursor="Hand" 
         Foreground="#555" Width="31" Margin="0 0 0 15"  
         HorizontalAlignment="Right">Close</Hyperlink>

    <Button Width="60" Margin="0 0 0 3">Test 1</Button>
    <Button Width="60" Margin="0 0 0 3">Test 2</Button>
    <Button Width="60" Margin="0 0 0 3">Test 3</Button>
    <Button Width="60" Margin="0 0 0 3">Test 4</Button>
</StackPanel>

Visual Studio Team: In Visual Studio 2010 I want Clippy to pop up and say "It seems you are trying to make a hyperlink" and tell me how to do it. Can't you do that with MEF? It would be retro cool, and these little "how do I do what I already know how to do in HTML" issues burn up so much time during the learning process with XAML.

回答1:

You can use a Button with a custom control template, the code below is a limited hyperlink style button (for example it only support textual hyperlinks) but maybe it'll point you in the right direction.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="Link" TargetType="Button">
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="Cursor" Value="Hand"/>
    <Setter Property="Foreground" Value="Blue"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <TextBlock TextDecorations="Underline" 
                    Text="{TemplateBinding Content}"
                    Background="{TemplateBinding Background}"/>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Foreground" Value="Red"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</Page.Resources>
<Button Content="Click Me!" Style="{StaticResource Link}"/>
</Page>


回答2:

You can't add a Hyperlink to a StackPanel -- you'll get a runtime error. (Actually, I'm kinda surprised it's not a compile-time error.) That's because Hyperlink doesn't live in the "controls" side of WPF with <Button> and <StackPanel> and other things that are laid out on rectangular chunks of screen and descend from UIElement. Instead, it lives in the "text" side of things, with <Bold> and <Run> and <Paragraph> and other generally texty things that word-wrap and flow in lines and paragraphs and descend from TextElement.

Once you realize that there are two separate class hierarchies with different layout behaviors, it makes sense that Hyperlink would be on the "text" side of things (makes it easy to e.g. have a paragraph with a hyperlink in the middle, and even for that hyperlink to wrap across a line break).

But no, it's not so discoverable when you're starting out.

To mix the two worlds, and use a hyperlink as a control, all you need to do is put it in a TextBlock. TextBlock is a control-ish thing (i.e., can go in a StackPanel) that contains text-ish things (i.e., can contain a Hyperlink):

<TextBlock><Hyperlink Click="buttonClose_Click">Close</Hyperlink></TextBlock>


回答3:

Try this:

<TextBlock>
    <Hyperlink RequestNavigate="Hyperlink_RequestNavigate" 
               NavigateUri="http://www.msn.com">MSN</Hyperlink> 
</TextBlock>

private void Hyperlink_RequestNavigate(object sender,
                                       System.Windows.Navigation.RequestNavigateEventArgs e)
{
    System.Diagnostics.Process.Start(e.Uri.AbsoluteUri);
}


回答4:

You may find that if you're binding to anything other than simple text values you will need to use ContentPresenter otherwise nothing will appear, this could be true if you're binding to an XML data source.

A Property Trigger for IsMouseOver gives the text an underline.

An example where I"m binding to XML is presented below.

<Style x:Key="JobNumberStyleButton" TargetType="{x:Type Button}">
  <Setter Property="VerticalAlignment" Value="Top"/>
  <Setter Property="HorizontalAlignment" Value="Left"/>
  <Setter Property="Cursor" Value="Hand"/>
  <Setter Property="Background" Value="Transparent"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <TextBlock>
          <ContentPresenter
            Margin="0,0,0,0"
            ContentTemplate="{TemplateBinding ContentTemplate}"
            Content="{TemplateBinding Content}"
            ContentStringFormat="{TemplateBinding ContentStringFormat}"
            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
            VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
            RecognizesAccessKey="False"
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
        </TextBlock>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
  <Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="Button">
            <TextBlock Padding="0,0,0,0" Margin="0,0,0,0">
              <Underline>
                <ContentPresenter
                  Margin="0,0,0,0"
                  ContentTemplate="{TemplateBinding ContentTemplate}"
                  Content="{TemplateBinding Content}"
                  ContentStringFormat="{TemplateBinding ContentStringFormat}"
                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                  RecognizesAccessKey="False"
                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
              </Underline>
            </TextBlock>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Trigger>
  </Style.Triggers>
</Style>


回答5:

<TextBlock>
  <Hyperlink NavigateUri="{Binding YourUri}" RequestNavigate="YourRequestNavigate">
   <TextBlock Text="{Binding YourText}" />
  </Hyperlink>
</TextBlock>

This will linkify any binded text in the nested textblock, i have not found a better way yet, i would like the first textblock to not be there if possible. This will work for DataTemplates aswell.



回答6:

You can simply use HyperlinkButton. When it is clicked on, the URL will be displayed in your web browser:

<HyperlinkButton
    NavigateUri="https://dev.windowsphone.com"
    TargetName="_blank"
    Content="Windows Phone Dev Center" />


回答7:

Usually, the meaning of an Hyperlink is to give an anchor to send the user to another Page or generally speaking to another resource, so it's implemented in such a way and you have to specify the location for that resource like this:

<HyperLink NavigateUri="http://www.site.com">
   Web Site
</HyperLink>

However, i've found this blog post with a custom TextBlock that is used as an HyperLink and supports click events.



回答8:

in UWP with mvvmcross i'm using this

  <HyperlinkButton Content="{Binding TextSource, ConverterParameter=MyUrl, Converter={StaticResource Language},
           FallbackValue=_MyUrl}" NavigateUri="http://www.google.com" />