Better Windows Phone Web Browsing

There's been a long-standing debate on the future of phone applications: Are they going to be HTML-based or remain native? Platform manufacturers such as Apple Inc. and Microsoft are keen to showcase the richness of their platforms, and thus invest heavily in encouraging developers to build native applications.

But there's a very strong argument in favor of HTML-based applications in that they can easily be repurposed for a variety of different platforms. There's also a middle ground, often referred to as hybrid, in which a native application hosts Web content. This can range from simply displaying HTML content, all the way through having all application logic and UI in HTML, JavaScript and CSS.

Let's take a look at the Windows Phone WebBrowser control, and how you can use it to display Web content. You'll also see that you can even customize the way content is displayed to make it appear as part of an application.

Start by adding the WebBrowser control to an empty page within the application. Also, point it at a page on the BBC Web site:

Before tailoring the page layout, let's try improving the loading experience. At the moment the page loads, the WebBrowser control will automatically attempt to render the page specified in the Source attribute.

While this might look OK when the user is on a high-speed network, or while you're debugging your application in the emulator, the reality is that most users will be on a much slower network and this page will take at least a few seconds to download and render. During this period the user will see a blank page with no visual indicators that something is actually happening.

The first task is to improve the experience by adding a progress indicator while content loads. In Expression Blend (right-click on your Windows Phone project in Visual Studio and click Open in Expression Blend), create two visual states that will show or hide elements on the screen for loading content and for when content has been loaded.

Locate the States tool window in Blend, click the Add state group button and rename the newly created state group to LoadingStates. Next, click the Add state button alongside the LoadingStates group and name the first state Loading. Now repeat this last step to create a state called Loaded. When you click on either of these states you'll notice a red dot appear beside the state, and that a red outline is added to the main design surface (see Figure 2). This indicates you're in "state editing mode," and that changes you make will be applied to that state. To exit state editing mode, click Base; this will return you to the page layout before any state transitions have been applied.

[Click on image for larger view.]

Figure 2.State editing mode in Expression Blend.

At this point, the Loaded state is essentially done, and the WebBrowser control is visible. For the Loading state, we'll need to add a ProgressBar and a TextBlock to the page to provide visual feedback to the user. We'll put these in a Grid that will mask the loading of the Web content, using the XAML in Listing 1 (which includes the two visual states just created).

The Grid that contains the progress indicator is currently Collapsed, so it isn't visible for either state. In the States window in Blend, select the Loading state and change the Visibility property on the GD_Progress element to Visible.

We also want to change the ProgressBar to show the progressive dots (similar to how the core platform shows indeterminate progress) by setting the IsIndeterminate property to True. Make sure that this is only set to True for the Loading state, to ensure it doesn't affect application performance when it isn't visible. The XAML for the visual states should now look like Listing 2.

The last part is to specify which state the page should be in, based on the loading of content in the WebBrowser control. This is made possible by attaching event handlers to the Navigating, LoadCompleted and NavigationFailed events on theWebBrowser control:

Running the application will show the progress indicator appear while the content is loading, then disappear when the page has been fully loaded.

Displaying the Page
The next thing to examine is how the page is actually displayed on the screen. Currently the user has to zoom and scroll the page to read the content. This isn't a great experience, and the content clearly looks like Web content that's been injected into the application.

To start, we're going to inject some CSS into the page, allowing the host application to adjust the layout of the Web content. Rather than writing ad hoc JavaScript to find and adjust the style on individual elements, we're going to add a CSS file to the Windows Phone application. When doing this, make sure the Build Action for the file is set to Content; this will ensure it gets deployed alongside your application on the device. After the WebBrowser has finished loading the page -- but before hiding the progress indicator -- we're going to load the contents of the CSS into a string, then inject it into the WebBrowser via the InvokeScript method (see Listing 3).

With the ability to apply CSS to any elements within the page, you can easily determine which elements to show or hide (using "display:none" to hide elements); override font color and size; and adjust element height, width and margins. In fact, you can completely customize the CSS for the page. Figure 3 illustrates the before (left) and after (right) of the page from the BBC Web site, where a number of the elements were hidden in order to clean up the layout.

While it's nice to be able to adjust the layout of page elements, it won't fit into the overall structure of the application if it doesn't maintain the theme you've used within your application. For example, if you were taking advantage of the Dark and Light themes on the phone, when you arrive at the page hosting the Web content, chances are it will have the wrong background or foreground. A strategy for handling this is to put placeholders in your CSS file where you would be setting the foreground and background colors. For example, the following CSS sets the foreground and background color for the "body" and "p" elements:

In this case, FGColor and BGColor are used as placeholders. Prior to sending this CSS to the browser, the code in Listing 4 is used to replace these with the actual theme colors set within the application.

In this article you've seen how to integrate Web content and style it to make it part of your application. Remember, though, that adjusting the layout can cause a noticeable lag in displaying the content. If you have the ability to influence the server-side code, it's much more desirable to tweak the presentation of the Web content based on the user agent string of the device. This will not only occur quicker on the server while preparing the content, but it will often result in less data being downloaded to the device.

About the Author

Nick Randolph runs Built to Roam, a consulting company that specializes in training, mentoring and assisting other companies build mobile applications. With a heritage in rich client applications for both the desktop and a variety of mobile platforms, Nick currently presents, writes and educates on the Windows Phone platform.