Full Web Browser Control for Windows Phone 7

27 03 2011

Web vs Native vs Hybrid Applications

Windows Phone development has a lot of flavors. There are three different ways to create Windows Phone applications: web based, native and hybrid applications. The first, web based applications, are done and hosted completely on the web and accessed using the phone browser. This type of application is the most portable because it can be accessed through most of the web browsers. The problem with creating web based mobile applications is that you lose most of the functionality that the platform can give you. The second way of creating a Windows Phone application is developing a native application. This type of application is the most commonly used  when you want to  takes advantage of the features that the platform has to offer. The problem with native applications is that cross platform maintenance tends to be a challenge because of the time and knowledge it consumes. And last but not least the best of the both worlds, what I like to call the Hybrid Mobile Application. This type of application enjoys the portability of a web based application and lets us work with the features that the platform can offer us. A an example of the advantages of a hybrid application would be a search application that uses the GPS on the mobile to get more accurate results and a web browser to show the results.

The Problem

Developing hybrid applications for the Windows Phone platform requires that we include a web browser control and extend the application with any feature with the phone functionality. But the problem that I have encountered while developing this type of applications is that the Web Browser Control included with the Windows Phone Developer Tools does not include any history or navigation as in forward, back and refresh. The lack of this functionality makes the web browser control hard to develop with. In this post we are going to be creating a browser control that enables forward, back and refresh navigation and also saves the history. Also we are going to include a progress bar to let the user know that we are navigating and that the application did not freeze.

Creating the Control

First we are going to create a Windows Phone Class Library Project on Visual Studio 2010.

  1. Open Visual Studio 2010 go to File->New->Project…
  2. Select Windows Phone Class Library from the project templates.
  3. Add FullBrowserControl to the project name
  4. Press Ok to create the project.
New Windows Phone Class Library Project

New Windows Phone Class Library Project

After creating the project delete the Class1.cs auto generated file and add a new Windows Phone User Control.

  1. Right click on the FullBrowserControl solution, Add->New Item
  2. In the dialog add a Windows Phone User Control and name it FullBrowserControl.xaml
  3. Click Ok.
New Windows Phone User Control Item

New Windows Phone User Control Item

Creating the Interface of Our Control

Once we have added the new User Control we are going to create our Full Browser Control’s user interface. For this we first need to download and install the Silverlight Toolkit for Windows Phone which includes a lot of new controls for Windows Phone and in particular the PerformanceProgressBar that we are going to be using to alert the user that the browser is navigating.  Now let’s add some row definitions to the User Control content grid:

<Grid Name="ContentGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>
</Grid>

Now we will add the PerformanceProgressBar and we are going to bind the IsIndeterminate property to a ShowProgress DependencyProperty that we are going to be creating in a moment.

<Grid Name="ContentGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>

        <toolkit:PerformanceProgressBar
            x:Name="performanceProgressBar"
            IsIndeterminate="{Binding ShowProgress}"
            Background="{StaticResource PhoneBackgroundBrush}"
        />
 </Grid>

And last but not least we are going to add a regular WebBrowser control. it is very important that the IsScriptEnabled property is set to true because we are going to be invoking JavaScript from the browser in order to navigate between pages. Also we are going to need the Navigated, Navigating and Loaded event handlers.

<Grid Name="ContentGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>

        <toolkit:PerformanceProgressBar
            x:Name="performanceProgressBar"
            IsIndeterminate="{Binding ShowProgress}"
            Background="{StaticResource PhoneBackgroundBrush}"
        />

        <phone:WebBrowser
            Name="TheWebBrowser"
            Grid.Row="1"
            Background="{StaticResource PhoneBackgroundBrush}"
            IsScriptEnabled="True"
            Navigated="TheWebBrowser_Navigated"
            Navigating="TheWebBrowser_Navigating"
            Loaded="TheWebBrowser_Loaded"
        />
 </Grid>

Now we need to open the FullWebBrowser.xaml.cs file to start working our logic.

Creating our Logic

In order to set up all the bindings correctly we need to set the DataContext of the grid to the FullWebBrowser object like this:

public partial class FullWebBrowser : UserControl
{
    //ctr
    public FullWebBrowser()
    {
        InitializeComponent();

        //Set the data context for the bindings.
        ContentGrid.DataContext = this;
    }
}

Now that we have set up the DataContext of our FullBrowserControl we are going to add some fields that we are going to be using for our logic. First we are going to add a Stack named  _NavigatingUrls that is going to be used to store the previous urls that we can navigate to. Then we need to add an ObservableCollection named _History that is where we are going to store the navigation history for our browser, we also need to create a readonly property named History that will let us access the _History field. And last but not least we need a flag to validate if the user is navigating back or not, for this we are going to use a bool variable named _IsNavigatingBackward with the false as the default value.

#region Fields

    //The navigation urls of the browser.
    private readonly Stack<Uri> _NavigatingUrls = new Stack<Uri>();

    //The history for the browser
    private readonly ObservableCollection<string> _History =
       new ObservableCollection<string>();

    //Flag to check if the browser is navigating back.
    bool _IsNavigatingBackward = false;

    #endregion Fields

    #region Properties

    /// <summary>
    /// Gets the History property for the browser.
    /// </summary>
    public ObservableCollection<string> History
    {
        get { return _History; }
    }

#endregion Properties

Now we are going to create three dependency properties. One is a ShowProgress boolean value that is the flag we are going to use to display our progress bar while we navigate in our browser also as you remember is the value that we binded to the IsIndefinite property of the PerformanceProgressBar. The second, a CanNavigateBack boolean value to determine if the browser is able to navigate back and the third a InitialUri string that is going to be the initial uri that our browser should navigate when the browser loads for the first time.

#region Dependency Properties

    /// <summary>
    /// ShowProgress Dependency Property
    /// </summary>
    public static readonly DependencyProperty ShowProgressProperty =
        DependencyProperty.Register("ShowProgress", typeof(bool),
        typeof(FullWebBrowser), new PropertyMetadata((bool)false));

    /// <summary>
    /// Gets or sets the ShowProgress property. This dependency property
    /// indicates whether to show the progress bar.
    /// </summary>
    public bool ShowProgress
    {
        get { return (bool)GetValue(ShowProgressProperty); }
        set { SetValue(ShowProgressProperty, value); }
    }

    /// <summary>
    /// CanNavigateBack Dependency Property
    /// </summary>
    public static readonly DependencyProperty CanNavigateBackProperty =
        DependencyProperty.Register("CanNavigateBack", typeof(bool),
        typeof(FullWebBrowser), new PropertyMetadata((bool)false));

    /// <summary>
    /// Gets or sets the CanNavigateBack property. This dependency property
    /// indicates whether the browser can go back.
    /// </summary>
    public bool CanNavigateBack
    {
        get { return (bool)GetValue(CanNavigateBackProperty); }
        set { SetValue(CanNavigateBackProperty, value); }
    }

    /// <summary>
    /// InitialUri Dependency Property
    /// </summary>
    public static readonly DependencyProperty InitialUriProperty =
        DependencyProperty.Register("InitialUri", typeof(string),
        typeof(FullWebBrowser), new PropertyMetadata((string)String.Empty));

    /// <summary>
    /// Gets or sets the InitialUri property. This dependency property
    /// indicates the initial uri for the browser.
    /// </summary>
    public string InitialUri
    {
        get { return (string)GetValue(InitialUriProperty); }
        set { SetValue(InitialUriProperty, value); }
    }

#endregion Dependency Properties

Now that we have all our Fields, Properties and Dependency Properties set up we need to create the event handlers that we added to the WebBrowser control.

#region Event Handlers

    void TheWebBrowser_Navigating(object sender,
        Microsoft.Phone.Controls.NavigatingEventArgs e)
    {
    }

    void TheWebBrowser_Navigated(object sender,
        System.Windows.Navigation.NavigationEventArgs e)
    {
    }

    private void TheWebBrowser_Loaded(object sender, RoutedEventArgs e)
    {
    }

 #endregion Event Handlers

First let’s start with the Loaded event. We are going to use the InitialUri and navigate to it.

#region Event Handlers

    void TheWebBrowser_Navigating(object sender,
        Microsoft.Phone.Controls.NavigatingEventArgs e)
    {
    }

    void TheWebBrowser_Navigated(object sender,
        System.Windows.Navigation.NavigationEventArgs e)
    {
    }

    private void TheWebBrowser_Loaded(object sender, RoutedEventArgs e)
    {
        //When we load our browser if we specified an initial uri
        //we navigate to it.
        if(!String.IsNullOrEmpty(InitialUri))
            TheWebBrowser.Navigate(new Uri(InitialUri));
    }

 #endregion Event Handlers

By using the Navigate method of the browser we activate the Navigating event. Every time that we start navigating we want to show the PerformanceProgressBar to alert the user that the browser is navigating. To do this we set the ShowProgress dependency property to true.

#region Event Handlers

    void TheWebBrowser_Navigating(object sender,
        Microsoft.Phone.Controls.NavigatingEventArgs e)
    {
        //We show the progress bar when we start navigating.
        ShowProgress = true;
    }

    void TheWebBrowser_Navigated(object sender,
        System.Windows.Navigation.NavigationEventArgs e)
    {
    }

    private void TheWebBrowser_Loaded(object sender, RoutedEventArgs e)
    {
        //When we load our browser if we specified an initial uri
        //we navigate to it.
        if(!String.IsNullOrEmpty(InitialUri))
            TheWebBrowser.Navigate(new Uri(InitialUri));
    }

 #endregion Event Handlers

The last event is the browser Navigated handler. Here is where we are going to be giving our control the logic to determine if he can navigate backward or forward and save a history of our navigation every time we go to a different url or navigate within a website. The first thing we are going to do is verify if we are navigating back or forward and if we can navigate back. If we are navigating forward meaning that the _IsNavigatingBackward flag is set to false we are going to add the new url, the one that we are navigating to, to our url stack, also we will add it to our history but only if the url is not already in our history. But if the _IsNavigatingBackward flag is set to true and we can navigate back we just need to remove the top url from our _NavigatingUrls stack. Then we check if there is only one url in our stack remaining. If there is more than 1 url in our stack that means that we can navigate back and we set the CanNavigateBack flag to true, if there is only one left the we cannot navigate back so we set the CannavigateBack flag to false. And last but not least we can hide our PerformanceProgressBar setting our ShowProgress dependency property to false.

#region Event Handlers

    void TheWebBrowser_Navigating(object sender,
        Microsoft.Phone.Controls.NavigatingEventArgs e)
    {
        //We show the progress bar when we start navigating.
        ShowProgress = true;
    }

    void TheWebBrowser_Navigated(object sender,
        System.Windows.Navigation.NavigationEventArgs e)
    {
        //If we are Navigating Backward and we Can Navigate back,
        //remove the last uri from the stack.
        if (_IsNavigatingBackward == true && CanNavigateBack)
            _NavigatingUrls.Pop();

        //Else we are navigating forward so we need to add the uri
        //to the stack.
        else
        {
            _NavigatingUrls.Push(e.Uri);

            //If we do not have the navigated uri in our history
            //we add it.
            if (!_History.Contains(e.Uri.ToString()))
                _History.Add(e.Uri.ToString());
        }

        //If there is one address left you can't go back.
        if (_NavigatingUrls.Count > 1)
            CanNavigateBack = true;
        else
            CanNavigateBack = false;

        //Finally we hide the progress bar.
        ShowProgress = false;
    }

    private void TheWebBrowser_Loaded(object sender, RoutedEventArgs e)
    {
        //When we load our browser if we specified an initial uri
        //we navigate to it.
        if(!String.IsNullOrEmpty(InitialUri))
            TheWebBrowser.Navigate(new Uri(InitialUri));
    }

 #endregion Event Handlers

Finally we need to add our private methods to navigate back, forward and refresh our FullBrowserControl. Let’s start with the navigate forward method. To navigate forward we simply need to set the _IsNavigatingBackward to false and invoke the JavaScript code to navigate forward (“history,go(1)”).

 /// <summary>
 /// Used to navigate forward.
 /// </summary>
 public void NavigateForward()
 {
     _IsNavigatingBackward = false;
     TheWebBrowser.InvokeScript("eval", "history.go(1)");
 }

Navigating back and refresh work in the same way as NavigateForward. When navigating back we set the _IsNavigatingBack to true and invoke the JavaScript code to navigate back (“history.go(-1)”).  To refresh our browser we only need to invoke the JavaScript code for refresh (“history.go()”)  and we do not need to set any flag because refreshing the browser does not activate neither the Navigating nor Navigated handlers of the browser so we do not change anything on our history or navigating uris.

 /// <summary>
 /// Used to navigate back.
 /// </summary>
 public void NavigateBack()
 {
     _IsNavigatingBackward = true;
     TheWebBrowser.InvokeScript("eval", "history.go(-1)");
 }

 /// <summary>
 /// Used to refresh the browser.
 /// </summary>
 public void RefreshBrowser()
 {
     TheWebBrowser.InvokeScript("eval", "history.go()");
 }

And the last method we are going to expose is a Navigate method that calls the internal Browser to navigate to a specified url.

 /// <summary>
 /// Used to navigate to a specified url.
 /// </summary>
 /// <param name="Url">The web address.</param>
 public void Navigate(string Url)
 {
     TheWebBrowser.Navigate(new Uri(Url, UriKind.Absolute));
 }

That is it. Our FullBrowserControl is ready. We have a browser that navigates to urls, navigates back, navigates forward, refresh and saves the history for us and let us handle the back button marketplace requirement with the CanNavigateBackward property when developing hybrid applications. To see how it works I am including the source code here (FullBrowserSample.zip).

P.S. There are some methods remaining like the InvokeScript and the InvokeScriptCompleted handler that can be exposed as needed.

Thanks’ everyone for reading. Come back later for more posts on Francisco’s Development Corner. ENJOY!!!!

About these ads

Actions

Information

30 responses

29 11 1999
Full Web Browser Control for Windows Phone 7 | www.nalli.net

[...] Source: Francisco’s Development Center [...]

17 04 2012
Raghav

Hello,
Can you tell me how to insert a search box for this full webBrowser control. Or Can you tell me the source code for this Navigation. Please mail me the source code – rghv.rocking@gmail.com.

27 03 2011
Emanuel Mendez

Great post Francisco, you explained the topic very well. This surely added something new to my knowledge.

29 03 2011
Ram

Hi Francisco, excellent control. Thank you very much for sharing it with us. Is copy and paste functionality available through this custom control? I haven’t seen it available in the standard Web Brower Control.

29 03 2011
fjfernandez

Hello Ram,

The browser already has the copy paste enabled. You might have not seen it because copy/paste will only be enabled for input text as in text boxes in app controls and Web. Text blocks or static/output text cannot be copied or pasted. So for now this is a copy/paste limitation. If you have the latest WP7 Emulator and Tools you should be able to try copy/paste, to do this simply open the sample app that I included in this post and do the following:

  1. Navigate to any page where you can input text such as http://www.bing.com.
  2. Write something in the search box.
  3. Un-focus the search box by clicking anywhere on the page.
  4. Re-select what you just wrote and the copy option should appear.

I hope this can help and thanks for reading.

Cheers,
Francisco J. Fernandez

17 04 2012
Raghav

Hello fjfernandez,
Can you tell me how to insert a search box for this full webBrowser control. Or Can you tell me the source code for this Navigation. Please mail me the source code – rghv.rocking@gmail.com.

29 03 2011
Full Web Browser Control for Windows Phone 7 | www.nalli.net

[...] Source: Francisco’s Development Center [...]

14 04 2011
Hjalmar Perez

Great post Francisco. I have a related question and I was hoping you could share your thoughts on it. I am getting back into SW development so although a lot of these new technologies are extremely new to me, I have been able to use the basic knowledge I had learned before to make sense of what I am trying to do.

Some background: I am basically wanting to communicate with a restful web service called Proxomo (Proxomo.com) and I am working specifically on calling it to perform the login functionality. Behind the scenes, Proxomo will not only log my application but also take care of logging me into Facebook since Proxomo is designed to be a portal to Facebook and other social network sites.

So I decided to create a webBrowser custom control to that me or anyone else wanting to log into Proxomo can call from their WP7 app by embedding the control into one of their xaml WP7 pages. Then, when the page containing the custom control is loaded, the Loaded event will navigate to the appropriate url in Proxomo (passing in the login parameters for login in the Querystring). Proxomo will then internally redirect through multiple other pages including Facebook for the user to log into Facebook. When the login process completes, Proxomo directs the browser to a “login result” page that has a specific url and that includes the results of the login operation in its Querystring (cancel, error, success).

So in the “Navigated” event handler I added code to monitor the url that is being navigated to when it detects that the browser has been asked to display this “login result” page, I will raise an event that I have defined in my browser control so the app can then handle the result properly (like sending the user to some other page in his app).

Using your example above, I was able to modify it and make it work for me! My understanding is that what I had created was then a USER CONTROL, not a CUSTOM control. One question I have is that now read this article about user controls vs. custom controls:
http://www.windowsphonegeek.com/articles/User-Control-vs-Custom-Control-in-Silverlight-for-WP7

and in the Table of Comparisons at the bottom of the article, the 4th comparison says that a USER control does NOT compile into a dll. However, I can see that your example compiles to a dll. So now I am confused, does your example create a User or a Custom control?

Thanks in advance,

Hjalmar

28 06 2011
techang

Thanks for the post. Do you know how to interact with the Web Browser Control to get the selected word in a navigated page? It seems the single click in IE Mobile will highlight and select a word. But, I cannot get it work in Web Browser control. Do you have any idea about that? Thanks.

18 07 2011
a developer

is it possilbe to manipulate the text box value served from server on windows phone 7? say i want to post the search string box on http://www.bing.com programattcally.

webBrowser.Document.forms.. manipulation is possible?

26 07 2011
Shankaran

Hi Francisco,
Thanks for sharing this excellent control. It works fine when i am using the URL bing,google,yahoo etc.But it showing “An unknown error has occurred. Error: 80020006″ while using the below URL
http://m.cvs.com

19 08 2011
robert bibr

this topic is so useful for me thanx

20 09 2011
Halley

consider such a case:

if the initurl response with 301 Moved,then the solution fails

23 10 2011
maxim

Hi, nice post, do you know how to navigate to open a link in a browser instead opening it in the webbroser control inside app? Another question: is it possible to play youtube video in webbrowser control?

29 12 2011
kakopappa

Thanks .

25 01 2012
Matthew

Great Post! Thanksfor the decisive information. I was wondering the best way to add button functionality to this code sample. For instance, placing buttons in a wp7 application and linking them to correct click events, as well as how to actually display the history (or bind it to a List) if someone wanted to examine previous websites and click on one to navigate to it directly from the history collection? Could u possibly offer some code help on the history navigation, I believe I could take care of the click events myself. Another cool and interesting consideration I thought was to add an optional Favorites category to save sites to a Favorites collection?
By the way I am new to Windows Phone programming and have grown to love it over the previous month or two of teaching myself. Any descriptive information or links to other websites for help would be greatly appreciated as well!

28 03 2012
Mayur

How to fetch the loaded,navigating url in the textbox after the loadcompleted event occurs in the class library file and how to show the loaded url on the textbox in the main page of application.

30 03 2012
Jalpa

Hey Fransisco,
I am unable to download your source code. I know this post is very old, please do try to help me download your sample.
I need to implement a web browser in my wp7 application and am facing issues in navigation & downloading files.
Thanks.

17 04 2012
Raghav

Can anybody tell me how to insert a search box for this full webBrowser control. Or Can anybody tell me the source code for this Navigation. Please mail me the source code – rghv.rocking@gmail.com.

28 10 2012
davidgerding

How all… I’ve got the source code but know amount of fiddling with the code seems to get me around the error: An unknown error has occurred. Error: 80020006.

It seems the assumption that we can can use ‘eval’ isn’t true anymore?

Anybody have any ideas?

Dave G

13 12 2012
Wilfred

Pretty section of content. I just stumbled upon your site and
in accession capital to assert that I get in fact enjoyed account your blog posts.

Anyway I will be subscribing to your feeds and even
I achievement you access consistently rapidly.

22 12 2012
read more

Good way of describing, and pleasant post to obtain information regarding my presentation subject matter, which i am going to present in school.

21 04 2013
kynanrobinsonmusic.blogspot.co.uk

Hi, after reading this amazing post i am as well cheerful to share my experience here with mates.

29 06 2013
Samson

Hi francisco,

I am just learning how to program mobile devices apps. The simple app that i decided to start with is the one that loads a particular website when an app icon is clicked. I succeseded to do it in Android, Iphone & Blackberry.
How can i do the same using webbrowser control in Windows Phone!!!!!

I need your help please!

17 07 2013
fjfernandez

Launching a website with the app icon I believe is not supported but what you can do is when you start your app load a web control pointing it to your website, but remember that you have to handle our back button as specified in the post so that you can navigate back in your site.

Thank You,
Francisco Fernandez

23 04 2013
Mitchel

Hello, I enjoy reading all of your post. I like to write a little comment to
support you.

17 07 2013
fjfernandez

Thanks Mitchel!!!! :-)

31 05 2013
http://www.theckn.com

Definitely believe that which you stated. Your favorite justification seemed to be
on the net the easiest thing to be aware of. I say to you, I definitely get irked while people consider worries that they plainly do not know about.

You managed to hit the nail upon the top as well as defined out
the whole thing without having side-effects , people can take a signal.
Will likely be back to get more. Thanks

17 07 2013
http://antipoliz.com

I every time spent my half an hour to read this blog’s articles or reviews all the time along with a cup of coffee.

28 07 2013
Path of Exile Act 1 Farming

It’s an awesome post designed for all the web users; they will take benefit from it I am sure.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




Follow

Get every new post delivered to your Inbox.

%d bloggers like this: