WPF中的Hyperlink(项目)
One question that has been coming up frequently over the past few days has been how to launch the browser when the user clicks on a hyperlink. The answer is different for the browser and standalone cases:
Browser (XBAP or Loose XAML)
XBAPs and loose XAML support special named targets for Hyperlink; these are the same named targets that are supported by HTML:
- _self: the browser should load the document in the same frame as the element that refers to this target
- _parent: the browser should load the document into the immediate parent frame of the current frame. This value is equivalent to _self if the current frame has no parent.
- _blank: the browser should load the document in a new, unnamed window
- _top: the browser should load the document into the full, original window (thus canceling all other frames). This value is equivalent to _self if the current frame has no parent.
The following XAML illustrates using a special target:
<TextBlock> <Hyperlink NavigateUri="http://microsoft.com" TargetName="_top"> Navigate the top-level window to Microsoft.com </Hyperlink> </TextBlock>
If you specify a target that does not exist, a new browser window will be created and the navigation will occur in that window. If you specify a target that already exists, the existing browser window will be used.
This functionality all relies on the named browser targeting feature that already exists in Internet Explorer. Note that the WPF navigation framework also supports named targets, so if you have a Frame in your Window named “_self,” “_top,” etc., those Frames will be searched first before delegating to the browser. This means that the hyperlink targeting logic will start by looking for an Avalon Frame inside the application with the specified name. If it does not find it, and the application is hosted in the browser, then it will call the browser’s navigate function with the specified target name.
I have a sample HTML page that hosts loose XAML in an iframe and demonstrates each of the special hyperlink targets. You can try it out here, and download both pages from here.
Standalone
Unfortunately WPF v1 does not have this convenient feature in the standalone case as well, since we can’t call into the browser in this case. For standalone scenarios, the simplest way to accomplish this task is to handle Hyperlink’s RequestNavigate event, and launch the default browser in your event handler.
The following XAML creates the Hyperlink and attaches an event handler:
<TextBlock> <Hyperlink RequestNavigate="HandleRequestNavigate" Name="hl" NavigateUri="http://microsoft.com"> Open Microsoft.com in the default browser </Hyperlink> </TextBlock>
And the following code implements the event handler:
void HandleRequestNavigate(object sender, RoutedEventArgs e) { string navigateUri = hl.NavigateUri.ToString(); // if the URI somehow came from an untrusted source, make sure to // validate it before calling Process.Start(), e.g. check to see // the scheme is HTTP, etc. Process.Start(new ProcessStartInfo(navigateUri)); e.Handled = true; }
You can download the source for this sample here.
实现的文章:
To user hyperlink in WPF application we could do something like this
<TextBlock> <Hyperlink NavigateUri=”http://www.google.co.in”> Click here </Hyperlink> </TextBlock>
However the NavigateUri works only if we are placing the hyperlink within a page. To use it within a windows-based application we need to hanlde the RequestNavigate event and write the code ourselves.
Something like this
<TextBlock> <Hyperlink NavigateUri=”http://www.google.co.in” RequestNavigate=”Hyperlink_RequestNavigate”> Click here </Hyperlink> </TextBlock>
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) { Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)); e.Handled = true; }
While using hyperlink we could also provide handler for Application.NavigationFailed event in case if navigation fails.
上面文章的practice:
Thanks, Krishna for your timely response. Thanks to Nishant Rana and also Ray Lopez's response in NR's weblog.
I did have the control as Hyperlink before, its just that I hadn't given all the details.
I had the event handled as the (Hyperlink) Click event as follows:
<Grid> <StackPanel> <TextBlock x:Name="txtTitle" Text="{Binding Path=Title}" Style="{StaticResource FontBig}"></TextBlock> <TextBlock Text="{Binding Path=Description}" Style="{StaticResource DescriptionStyle}"></TextBlock> <TextBlock> <Hyperlink NavigateUri="{Binding Path=Url}" Click="Hyperlink_Click"> <TextBlock Text="{Binding Path=Url}" /> </Hyperlink> </TextBlock> <Label></Label> </StackPanel> </Grid>
Now according to Nishant Rana's Weblog - I modified the event handler from Click to
RequestNavigate (RequestNavigate="Hyperlink_RequestNavigate") and it works.
And I have the event handler code as follows
[ Note: I had to use the System.Diagnostics namespace in order to use the Process class etc., ]
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) { //I intend to make use of this error message at a later stage, for now it is informational only string errMsg = ""; try { Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)); e.Handled = true; } catch (UnauthorizedAccessException uae) { errMsg = uae.Message; } catch (WebException we) { errMsg = we.Message; } catch (Exception ex) { errMsg = ex.Message; } }
Then, next I tried to put in the Navigation failed event as per Ray Lopez's response
(at the bottom of Nishant Rana's weblog) where he suggests to put
private void App_NavigationFailed(object sender, NavigationFailedEventArgs e)
in the App.xaml (i.e. in App.xaml.cs file)
NOTE: I had to use the System.Windows.Navigation namespace for the NavigationFailed event and its args to be
accessible.