Derik Whittaker



Navigating to an external URL using the HyperlinkButton.

If you have ever tried used the HyperlinkButton inside your WP7 application and navigate to an external URL you are familiar with the following error.

"Navigation is only supported to relative URIs that are fragments, or begin with '/', or which contain ';component/'.\r\nParameter name: uri"

Basically when you set the NavigateUri property to anything that is not a local view you will get bad results.  I wanted to build out a version of the HyperlinkButton which not only allows you to navigate to an external url via the WebBrowserTask but I also wanted something that was MVVM friendly.  To accomplish these goals I needed to do the following:

Create a custom HyperlinkButton control called HyperlinkCommandButton

public class HyperlinkCommandButton : HyperlinkButton
    public HyperlinkCommandButton()
        Click += ( sender, e ) =>
                            if ( Command != null && Command.CanExecute( CommandParameter ) )
                                Command.Execute( CommandParameter );

    public static DependencyProperty CommandProperty =
        DependencyProperty.Register( "Command",
                                        typeof( ICommand ), typeof( HyperlinkCommandButton ),
                                        new PropertyMetadata( null, CommandChanged ) );

    private static void CommandChanged( DependencyObject source, DependencyPropertyChangedEventArgs args )
        var button = source as HyperlinkCommandButton;
        if ( button == null ) return;

        button.RegisterCommand( args.OldValue as ICommand, args.NewValue as ICommand );

    private void RegisterCommand( ICommand oldCommand, ICommand newCommand )
        if ( oldCommand != null )
            oldCommand.CanExecuteChanged -= HandleCanExecuteChanged;

        if ( newCommand != null )
            newCommand.CanExecuteChanged += HandleCanExecuteChanged;

        HandleCanExecuteChanged( newCommand, EventArgs.Empty );

    private void HandleCanExecuteChanged( object sender, EventArgs args )
        if ( Command != null )
            IsEnabled = Command.CanExecute( CommandParameter );

    public ICommand Command
        get { return GetValue( CommandProperty ) as ICommand; }
        set { SetValue( CommandProperty, value ); }

    public static DependencyProperty CommandParameterProperty =
        DependencyProperty.Register( "CommandParameter",
                                        typeof( object ), typeof( HyperlinkCommandButton ),
                                        new PropertyMetadata( null ) );

    public object CommandParameter
        get { return GetValue( CommandParameterProperty ); }
        set { SetValue( CommandParameterProperty, value ); }

Create a ViewModel (which is based of of the MvvM Light framework)

public class MainPageViewModel : ViewModelBase
    public MainPageViewModel()
        Url = "";
        InvokeUrlCommand = new RelayCommand( HandleUrl );

    private void HandleUrl( string url )
        var webBrowserTask = new WebBrowserTask { URL = url };

    public ICommand InvokeUrlCommand { get; set; }

    private string _url;
    public string Url
        get { return _url; }
            _url = value;
            RaisePropertyChanged( "Url" );

Hookup the ViewModel to the HyperlinkCommandButton

<WP7_HyperlinkTextPoc:HyperlinkCommandButton Content="HyperlinkButton" Height="30" HorizontalAlignment="Left" Margin="106,191,0,0" Command="{Binding InvokeUrlCommand}" CommandParameter="{Binding Url}" x:Name="hyperlinkButton2" VerticalAlignment="Top" Width="200" />

After you have created your custom HyperlinkButton which supports commanding and you have setup the ICommand correctly in your ViewModel you can see that enabling it in Xaml is cake.  You should also notice that I am NOT using the NavigateUrl property on the control, this is because I want to handle everything via the command which was wired up.

Now in my example I am NOT checking the URL to see if it is truly a public web address but this would be very easy to do if you want it.

Till next time,

Posted 01-01-2011 1:36 PM by Derik Whittaker
Filed under: ,


About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Google Reader or Homepage Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of
Red-Gate Tools For SQL and .NET


SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
NHibernate Profiler
Balsamiq Mockups
JetBrains - ReSharper
Web Sequence Diagrams
Ducksboard<-- NEW Friend!


Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers


Community Server (Commercial Edition)