Showing posts with label windows 8 apps. Show all posts
Showing posts with label windows 8 apps. Show all posts

Wednesday, June 19, 2013

MVVM and Accessing the UI Thread in Windows Store Apps

Any developer who has worked with MVVM in WPF, Silverlight, or Windows Store apps has likely run into the issue of executing an action on the UI thread. This most often happens when work has to be done on another thread. It is a common mistake to perform the work and then attempt to set a property on the view model. The view model exposes properties for data-binding, and data-binding must happen on the UI thread. Therefore, triggering a property change notification on the wrong thread can lead to a thread access violation and result in a crash. It is also necessary to access the UI thread when performing UI-related actions such as showing a modal dialog and waiting for user input.

I’ve seen a lot of different approaches to doing this, some of them quite complex and interesting to read, but a simple solution is easier than you might think. You can choose to set a property on the view model that references the UI thread:

private readonly CoreDispatcher dispatcher;

The dispatcher class queues messages for publication on the UI thread. The messages are callbacks of type DispatchHandler which is simply a named delegate. The dispatcher allows you to specify a priority for the message and higher priority messages will be queued in front of lower priority messages. I’ve rarely found the need to use anything other than the normal priority when performing work on the UI thread.

In this example I’m using a simple property to capture the dispatcher, but you may want to consider creating an interface that mimics the work the dispatcher does. Then you can implement a reference to the dispatcher at runtime but use a mocked implementation for tests.

Grabbing the right dispatcher is easier than you might think. I’ve seen solutions that use dependency properties and data-binding or wire up the dispatcher using code-behind, etc. but the reality is the view model is almost always instantiated on the UI thread (this is true whether it is created in code behind, referenced as a resource or instantiated directly from XAML). Therefore, you can simply capture the dispatcher in the constructor. Be sure you check for design-mode as the attempt to capture the dispatcher will fail in the designer.

if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
    return;
}
this
.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;

Now that I have captured the dispatcher, I can create a simple method that encapsulates the call to the UI thread (in this case I’m assuming it’s on the view model, but again this could be in an implementation that is referenced via an interface to make it easier to mock for testing).

private async Task OnUiThread(Action action)
{
    await this.dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => action());
}

This is a simple form – it takes an action and simply waits for the dispatcher to queue the callback on the UI thread. The following example will queue the assignment of a property on the UI thread so that data-binding can process the update (note there is another technique with view models that involves always marshalling the property change event to the UI thread). The following code is executed from a background task that is not running on the UI thread:

await this.OnUiThread(() =>
{
this.ViewModelProperty = this.BackgroundWork();
});

This will work for most cases, but if you are scheduling something asynchronous you’ll have a problem. The method I showed performs a “fire and forget” of the work you pass to it. If you are doing something like waiting for a dialog, your code may not behave as intended because it won’t actually wait for the dialog to close – instead, it will simply wait for the call to open the dialog to be scheduled. To solve this, provide a simple overload:

private async Task OnUiThread(Func<Task> action)
{
    await this.dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () => await action());
}

The overload also schedules a task, but it also acknowledges the task is asynchronous and awaits the completion of the task. Now you can schedule the work like this:

var dialog = new MessageDialog(message, title);
await this.OnUiThread(async () => await dialog.ShowAsync());

One important thing to keep in mind is that this should be the exception, not the rule, for most apps. A good design will not attempt to manipulate the view model directly, but instead will return a property and allow you to await the task from the UI thread. For example, setting the view model property might be accomplished like this without having to use the dispatcher at all:

this.ViewModelProperty = await this.BackgroundWorkAsync();                       

The dispatcher is most useful when you have scenarios that force you to spawn background tasks that you aren’t able to await from the UI thread, or when you have methods that may be called from a separate thread and must surface information to the UI.

Monday, June 10, 2013

Simple Validation with MVVM for Windows Store apps

Developers who are writing Windows Store apps using C# and XAML might find some of the support for Model-View-ViewModel (MVVM) lacking. Both WPF and Silverlight provided specific interfaces that enabled you to store validation context about fields on a context and even supported asynchronous validation. Although there are some existing frameworks that provide this support, such as Prism for the Windows Runtime, it is also fairly simple and straightforward to roll your own.

I do appreciate the various MVVM frameworks that exist (I’ve even written one of my own) but I find that most of the support I need for Windows Store apps comes out of the box. If you create your project from any of the built-in templates, the classes you need are already generated. In the case of the Blank app template, you simply need to add a single BasicPage item to get the supporting classes for layout-aware apps with intrinsic MVVM support. My favorite class is the BindableBase that provides basic property change notification and a special way to set properties that only triggers change notification if the new value differs from the old.

I use this to create a ValidationErrors class that is simply a collection of errors with a validation flag.

public class ValidationErrors : BindableBase  
{
    private readonly Dictionary<string, string> validationErrors = new Dictionary<string, string>();

    public bool IsValid
    {
        get
        {
            return this.validationErrors.Count < 1;
        }
    }
}

The indexer handles storing the errors and raising the appropriate property change notification so the dictionary can be bound in the UI.

public string this[string fieldName]
{
    get
    {
        return this.validationErrors.ContainsKey(fieldName) ? 
            this.validationErrors[fieldName] : string.Empty;
    }



    set
    {
        if (this.validationErrors.ContainsKey(fieldName))
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                this.validationErrors.Remove(fieldName);
            }
            else
            {
                this.validationErrors[fieldName] = value;
            }
        }
        else
        {
            if (!string.IsNullOrWhiteSpace(value))
            {
                this.validationErrors.Add(fieldName, value);
            }
        }
        this.OnPropertyChanged();
        this.OnPropertyChanged("InValid");
    }
}

Note this implementation simply removes the item. It also supports a single message per item, it could be enhanced by providing a dictionary of lists if you want to support multiple errors per field.

The next step is to create a base class for validations to use.

public abstract class ValidationBase : BindableBase
{
    protected ValidationBase()
    {
        this.ValidationErrors = new ValidationErrors();            
    }

    public ValidationErrors ValidationErrors { get; set; }

    public bool IsValid { get; private set; }

    public void Validate()
    {
        this.ValidationErrors.Clear();
        this.ValidateSelf();
        this.IsValid = this.ValidationErrors.IsValid;
        this.OnPropertyChanged("IsValid");
        this.OnPropertyChanged("ValidationErrors");
    }

    protected abstract void ValidateSelf();
}

Now you can implement the validation in your class. The current implementation assumes you have a validation method that fires at the end, but you could easily enhance it to validate specific items as they are input as well. The sample class is a simple note with a title and description, and both are required to be filled out for validation to pass.

protected override void ValidateSelf()
{            
    if (string.IsNullOrWhiteSpace(this.title))
    {
        this.ValidationErrors["Title"] = "Title is required.";
    }

    if (string.IsNullOrWhiteSpace(this.description))
    {
        this.ValidationErrors["Description"] = "You must type some text for the note.";
    }            
}

Now that the validation is in place, you can easily bind to it in the UI. In this case I’m not using any converters because I want the space for the validation text to remain even if the fields are valid. This prevents the UI from shifting unnaturally. The save command simply calls the Validate method on the note and only saves it if the result is true. Take a look at the XAML and note how the indexers are used to display the validation message.

<TextBlock Text="Title:" Style="{StaticResource PageSubheaderTextStyle}"/>
<
TextBox Text="{Binding Title, Mode=TwoWay}" Grid.Row="1"/>
<
TextBlock Text="{Binding ValidationErrors[Title]}"
Foreground="Red" Grid.Row="2" Style="{StaticResource ItemTextStyle}" Margin="12 0 0 0"/>
<
TextBlock Text="Notes:" Style="{StaticResource PageSubheaderTextStyle}" Grid.Row="3"/>
<
TextBox Text="{Binding Description, Mode=TwoWay}" Grid.Row="4" TextWrapping="Wrap"/>
<
TextBlock Text="{Binding ValidationErrors[Description]}"
Foreground="Red" Grid.Row="5" Style="{StaticResource ItemTextStyle}" Margin="12 0 0 0"/>    

That’s it … now I have a simple way to validate entities and provide messages to the UI through MVVM. The final result looks like this (obviously some more work can be done to highlight the input box itself and style the page, but you should get the general idea).

safenotes

For the full working example (that includes how to use the WinRT data protection provider to encrypt notes) visit http://winrtexamples.codeplex.com/

Tuesday, June 4, 2013

Single Sign On with OAuth in Windows Store Apps

Various providers often provide documentation and even SDKs that make it easier to connect with and authenticate to their service. The problem is that most scenarios assume a web-based application or specific mobile clients. The process in general looks something like this:

oauth

How can you take protocol modeled for the web and make it work in an app that is running on a Windows 8 device? The answer is the WebAuthenticationBroker component in the Windows Runtime.

The web authentication broker is designed to assist you with single sign-on scenarios by emulating a fully web-based experienced. You provide the broker with a starting URL. This URL typically contains information such as special application codes and passwords used to verify your app’s identity with the provider and a redirect URL the provider should send the user to when they are authenticated. You also provide the broker with an ending URL. This is where the magic happens for the broker.

The broker starts by popping up a dialog that is essentially a web browser window without chrome. The user will be presented with the provider’s login page, such as the Facebook example shown here.

facebooksso

The user can then enter their credentials and authorize the app to information. Once they are finished, the provider will redirect them to a final URL. The web broker is configured to listen for this URL, and instead of serving the page, it will intercept the request and provide the details to your app. You can then parse the content of the redirect to obtain the access token that validates the user’s identity and can be used to make further requests from the provider.

The logic to authenticate with Facebook and receive a token is fairly straightforward. There are two URLs involved. The first is the URL used to authenticate with Facebook that we’ll call FaceBookAuth. The URL must be passed a client id (your app id), a redirect URL to send the user to when they are authenticated, a scope to determine what information you will be requesting, and the type of response (we want a token).

The second URL is the redirect URL. Because the example is a client app and not a web page, Facebook’s own confirmation URL is used as the redirect URL and stored in the FacebookRedirectUri constant. After the user authenticates, they will be redirected to the Facebook page. The web authentication broker will be listening for the redirect and will intercept it. The scope informs Facebook what you intend to access, for example, an email.

private const string FaceBookAuth =
https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri={1}&scope={2}&response_type=token;
private const string FacebookRedirectUri = "https://www.facebook.com/connect/login_success.html";

The code builds the start and end URLs and then calls the AuthenticateAsync method on WebAuthenticationBroker in the Windows.Security.Authentication.Web namespace. It is passed a set of options, the URL to start with, and the URL to listen to.

WebAuthenticationResult result = await WebAuthenticationBroker.AuthenticateAsync(

                                        WebAuthenticationOptions.None,
                                        startUri,
                                        endUri);

The authentication options are provided by passing flags specified in the WebAuthenticationOptions enumeration. Possible values include:

  • None – no options.
  • SilentMode – used for pure SSO that has no UI involved. If the provider displays a web page the authentication will fail.
  • UseTitle – instructs the web authentication broker to parse the title of the window for the web page and return it in the ResponseData property to allow you to parse it as needed.
  • UseHttpPost – when the provider performs a POST to the final website, this option will provide the contents of the POST in the ResponseData property.
  • UseCorporateNetwork – this will render the web page in a special container that supports enterprise authentication and private networks for intranet authentication and requires that similar capabilities are declared for the app.

The result will return a response status (successful, an HTTP error, or the user canceled) and the contents of the final redirect. The Facebook redirect uses a hash to separate the URL from a set of response parameters send in a query string format (name/value pairs). The first parameter is the token you can use for further access, and the second is when the token will expire. Use this to store the token and reuse it without having to request a new one each time.

if (result.ResponseStatus == WebAuthenticationStatus.Success)

{
    var data = result.ResponseData.Substring(result.ResponseData.IndexOf('#'));
    var values = data.Split('&');
    var token = values[0].Split('=')[1];
    var expirationSeconds = values[1].Split('=')[1];
    var expiration = DateTime.UtcNow.AddSeconds(int.Parse(expirationSeconds));
    this.dataStorage.Save(this.Name, expiration, token);
    return token;
}

Once the token has been received, the main authentication step is complete. Now you can use the token to request information about the user. For example, you can obtain their preferred email address to default it without asking or to identify the user internally to your app.

private const string FacebookIdentityUrl = "https://graph.facebook.com/me?scope=email";
public async Task<string> GetEmail(string accessToken)

{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue
("OAuth", accessToken);
    var result = await client.GetStringAsync(FacebookIdentityUrl);
    var profileInformation = JsonObject.Parse(result);
    var email = profileInformation["email"].GetString();
    return email;
}

You may have noticed earlier that an API was used to save the token. Tokens have expirations and can be reused so you don’t have to force the user to login in repeatedly. A safe and secure way to store tokens that will even roam to other devices (provided the user uses their Microsoft Account and the devices are trusted) is the credential locker. The locker expects a resource (such as the name of the provider), a username, and a password. For this example, the username is fixed and the password is used to store the token and the expiration:

public void Save(string key, DateTime expiration, string token)

{
    var vault = new PasswordVault();
    var credential = new PasswordCredential(
        key, 
        Username, 
        string.Format("{0}|{1}", expiration, token));
    vault.Add(credential);
}

The vault can be queried for the credential and the expiration is used to determine whether the token can be used again or not. If the user requests to sign out, the credential is simply removed from the locker.

For a working code example visit http://winrtexamples.codeplex.com and download the Chapter 8 AuthenticationExamples app. It demonstrates single sign on and retrieval of email for both Facebook and Google. You will need to have developer accounts for each and will have to update the code with your client ids and client secrets for the project to run.

Monday, May 20, 2013

Quick Tip: Processing HTML Content in Windows Store Apps

The WebView control allows you to display content from sites in your app using a small window that renders the HTML using the same rendering engine as Internet Explorer. It does have some limitations and most likely if you are providing content in your app, your goal is to augment your app with fresh data rather than try to superimpose a full-blown web application on your own native Windows Store app.

Trying to strip down content can be quite cumbersome once you wade through the myriad RegEx expressions or other utilities available. Here’s a simple trick that will work with most content-oriented sites like blogs and online magazines. It allows you to get a more basic view of the content and present it without all of the bells and whistles you may end up pulling down with regular content.

Step 1: Be Mobile

When you are loading content, make the server believe you are mobile. This will often result in a simpler page being presented, often without the heavy script tags or headers, table of contents, and other sections included. Here’s a nice mobile user agent string that will impersonate one of the most popular mobile clients out there, an iPhone:

private const string MobileUserAgent = "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3";

With the mobile header you can override the user agent and request the content. Instead of having the WebView control load the page directly, use the HttpClient and grab the content like this:

var handler = new HttpClientHandler { AllowAutoRedirect = true };

var
client = new HttpClient(handler);
client.DefaultRequestHeaders.Add("user-agent", MobileUserAgent);
var
response = await client.GetAsync(new Uri(InsertSuperAwesomeUrlHere));
response.EnsureSuccessStatusCode();
var
html = await response.Content.ReadAsStringAsync();

Allowing redirects is important because many pages will auto-detect your mobile client and instead of dynamically serving content will redirect you to a new page for the mobile content. This allows the client to follow the redirect and then pull down the content that is tailored to mobile devices. At this stage you may think you have what you need, but if you pass this to the WebView control you’ll find there is often script content trying to make updates that will throw exceptions and generally cause the WebView to choke. Next you must cleanse the data.

Step 2: Cleanse the Content

Cleansing the content may be easier than you think. It turns out that you need to have clean HTML to share HTML content with other Windows Store apps. In fact, the sharing mechanism provides a nice HtmlFormatHelper class (located in the Windows.ApplicationModel.DataTransfer namespace) designed to package your HTML so it is ready for sharing. It also contains a useful GetStaticFragment method that will strip out the dynamic code so you have nice, clean content. The trick is to prep the HTML as if you were going to share it, then get the static fragment so you have the raw text you can load.

var fragment = HtmlFormatHelper.GetStaticFragment(HtmlFormatHelper.CreateHtmlFormat(html));

Now you are ready to show it to the user.

Step 3: Show it to the User

Now that you have clean HTML, you can ask the WebView control to navigate to the string like this:

WebViewControl.NavigateToString(fragment);             

That’s all there is to it, and you should get a nice, clean page of data without dynamic tags.

Monday, May 6, 2013

A Fluent Approach to Windows Store Tiles

Windows Store apps have a variety of tricks up their sleeve for engaging the user even when they are not running. Tiles are a perfect example because they provide at-a-glance information to the user from the start screen. Tiles can provide images, text, or a combination of both and support queuing multiple notifications.

Tiles are defined by various pre-built XML templates. The catalog of tiles is available online in the tile template catalog and can be enumerated via TileTemplateType as defined in the Windows.UI.Notifications namespace. The sample apps for Windows 8 from Microsoft include a helper that allows you to create tiles but it requires instantiating specific classes. I wanted to create a more straightforward and fluent method for defining and setting tiles.

It turns out you can get the template for any tile type by calling GetTemplateContent on the TileUpdateManager class with the TileTemplateType you are interested in. Here’s a fast way to get the XmlDocument:

this.xml = TileUpdateManager.GetTemplateContent(templateType);

With the template I can easily inspect how many lines of text and images it is capable of supporting:

this.TextLines = this.xml.GetElementsByTagName("text").Count;
this.Images = this.xml.GetElementsByTagName("image").Count;

Now I can add text and raise an exception if the amount of text the tile can hold is exceeded:

public BaseTile AddText(string text, uint id = 0)
{
     if (string.IsNullOrWhiteSpace(text))
     {
         throw new ArgumentException("text");
     }
     if (id == 0)
     {
         id = this.textIndex++;
     }
     if (id >= this.TextLines)
     {
         throw new ArgumentOutOfRangeException("id");
     }
     var elements = this.xml.GetElementsByTagName("text");
     var node = elements.Item(id);
     if (node != null)
     {
         node.AppendChild(this.xml.CreateTextNode(text));
     }
     return this; }

Notice that the method returns the class instance itself. This sets the class up to support a fluent interface with multiple commands chained together. The same logic is used to add images. When you allow your app to provide both a wide and traditional square tile, you can update both formats with a single call. Therefore, you should be able to merge the definitions of multiple tiles:

public BaseTile WithTile(BaseTile otherTile)
{
     var otherBinding = this.xml.ImportNode(
        otherTile.xml.GetElementsByTagName("visual")[0].LastChild,
        true);
     this.xml.GetElementsByTagName("visual")[0].AppendChild(otherBinding);
     return this; }

Now we can grab the template for a tile, specify text and images, and combine square and rectangular tiles together. The next step is to actually set the tile for the app:

public void Set()

{
    TileUpdateManager.CreateTileUpdaterForApplication().Update(
        new TileNotification(this.xml));
}

I then added an extension method that takes in the type of the tile and returns an instance of my helper class that contains all of the methods described in this post. Putting it all together, the code to set a wide and square tile for an example app I’m building that enumerates all tiles on the system to display the XML looks like this:

// set some default tiles 
TileTemplateType.TileWideText03.GetTile()

                    .AddText("Tile Explorer")
                    .WithTile(TileTemplateType.TileSquareText03.GetTile()
                        .AddText("Tile Explorer")
                        .AddText("A WinRT Example")
                        .AddText("by Jeremy Likness"))
                    .Set();

This certainly makes it easier to update tiles. A complete helper will also include similar methods for badges and notifications of course … that’s all part of the work I’m doing. Full source and examples will be available in my upcoming book and I’ll share more details when I have them.

Thursday, April 4, 2013

Design-time Data for Windows Store Apps with C#

One of my favorite features of XAML is the ability to provide design-time data. This feature is present in WPF, Silverlight, and of course Windows Store apps. The great thing about design-time data is that the developer can create it programmatically when needed or the designer can generate some through Blend. In this post I will share an example of generating design-time data through code. The example is a project I am working on for my upcoming book, and can be downloaded from the website (still in its very early stages) from CodePlex.

In Chapter 5 I am covering the various options for interacting with web services. A company called CDYNE Corporation provides a nice, free weather service that is useful for demonstrating how to connect to a SOAP service. Yes, I know everything today is about REST but trust me, the SOAP services are still around. I’m just glad that the committee that governs the standard was wise enough to declare it is no longer an acronym. In case you didn’t know, SOAP originally stood for “Simple Object Access Protocol” but there was really nothing simple about it. Fortunately Microsoft saw wisdom in WSDL and was kind enough to provide the ability from Visual Studio 2012 to generate a proxy for you.

The focus of this post is design-time data, not web services, so let’s focus on the problem at hand. The web service I am referring to provides two APIs I’ll be using. One will resolve a zip code to a city and provide a forecast, and the other takes various weather “types” and provides a corresponding URL so that you can show a friendly icon for “sunny” or “cloudy” etc.

The first step I take is to model the result. Although I could use the model generated by the proxy, I find it’s often better to create your own domain model with the pieces you want so you don’t have to take a dependency on the service itself. You can easily map the service model to a domain model. The main service returns a result that provides the city and state (if it was successfully resolved) and a collection of entries that represent the forecast for each day of the upcoming week.

A “forecast” generated by the service looks something like this (taken from the proxy itself):

public partial class Forecast : object, System.ComponentModel.INotifyPropertyChanged 
{
         private System.DateTime dateField;
         private short weatherIDField;
         private string desciptionField;
         private temp temperaturesField;
         private POP probabilityOfPrecipiationField;
}

I’ll model it a little differently. Some developers will cry out and gnash their teeth when they see me exposing a property to convert the date instead of using a value converter, but I say … cry away. Here is the entry:

public class ForecastEntry

{
     public DateTime Day { get; set; }
     public string DayText
     {
         get
         {
             return this.Day.Date.ToString("D");
         }
     }
     public int TypeId { get; set; }
     public string Description { get; set; }
     public string PrecipitationDay { get; set; }
     public string PrecipitationNight { get; set; }
     public string TemperatureLow { get; set; }
     public string TemperatureHigh { get; set; }
     public Uri ForecastUri { get; set; } }

And here is the extension method to convert from the service to an instance of my domain entry:

public static ForecastEntry AsForecastEntry(this Forecast forecast)

{
     return new ForecastEntry
     {
         Day = forecast.Date,
         Description = forecast.Desciption,
         PrecipitationDay = forecast.ProbabilityOfPrecipiation.Daytime,
         PrecipitationNight = forecast.ProbabilityOfPrecipiation.Nighttime,
         TemperatureLow = forecast.Temperatures.MorningLow,
         TemperatureHigh = forecast.Temperatures.DaytimeHigh,
         TypeId = forecast.WeatherID
     }; }

That was easy enough – and would have been even easier with a tool like AutoMapper. Now we can create a simple user control that displays a single entry. Here is the XAML (keep in mind I get paid mostly for development, not design):

<Border Width="230" Height="200" Background="DarkBlue" CornerRadius="20">

<
Grid d:DataContext="{Binding Source={d:DesignInstance Type=data:DesignForecastEntry, IsDesignTimeCreatable=True}}"        Margin="10"        Width="210">
     <Grid.RowDefinitions>
         <RowDefinition Height="40"/>
         <RowDefinition Height="60"/>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="Auto"/>
     </Grid.RowDefinitions>
     <TextBlock Text="{Binding DayText}"
                TextWrapping="Wrap"
                Style="{StaticResource BodyTextStyle}"
                HorizontalAlignment="Center"/>
     <Image Width="50" Height="50" Grid.Row="1">
         <Image.Source>
             <BitmapImage UriSource="{Binding ForecastUri}"/>
         </Image.Source>
     </Image>

     <TextBlock Text="{Binding Description}"
                Grid.Row="2"
                Style="{StaticResource CaptionTextStyle}"
                HorizontalAlignment="Center"
                Margin="5"/>
     <StackPanel Grid.Row="3"
                HorizontalAlignment="Center"
                Orientation="Horizontal">
         <TextBlock Text="Low:"/>
         <TextBlock Text="{Binding TemperatureLow}" Margin="10 0 0 0"/>
         <TextBlock Text=" / High:"/>
         <TextBlock Text="{Binding TemperatureHigh}" Margin="10 0 0 0"/>
     </StackPanel>
     <StackPanel Grid.Row="4" Orientation="Horizontal"
             HorizontalAlignment="Center">
         <TextBlock Text="Chance of Precipitation:"/>
         <TextBlock Text="{Binding PrecipitationDay}" Margin="10 0 0 0"/>
     </StackPanel> </Grid> </Border>

There is no way I would be clever enough to design that simply by tapping out XAML and I’m far too lazy to put an entry and then run the app and repeat. In fact, I like to build from the bottom up – in other words, I worked on the forecast entry first, then the entire forecast, then the page to request the forecast, so if I didn’t have design-time data it would be impossible for me to preview the app before I wired everything in! If you can eyeball that XAML and tell me what it looks like … wow. More power to you! I, on the other hand, just created a simple class:

public class DesignForecastEntry : ForecastEntry

{
     public DesignForecastEntry()
         {
             this.Day = DateTime.Now;
             this.ForecastUri = new Uri(

http://ws.cdyne.com/WeatherWS/Images/mostlycloudy.gif,
UriKind.Absolute);
             this.Description = "Sample day for weather";
             this.PrecipitationDay = "50";
             this.PrecipitationNight = "20";
             this.TemperatureLow = "25";
             this.TemperatureHigh = "49";
             this.TypeId = 1;
         } }

Now the reference in the XAML makes sense. Specifically, you can specify a d:DataContext that is a data context only used at design time. You pass the type and inform the designer that it can be instantiated, and then in design-time you get something beautiful like this:

weatherentry

The best part? Even with my aesthetically challenged design skills, I can tweak the XAML and see the changes reflected immediately. I’m not complaining about the end result, are you? Now there is the whole forecast that I modeled like this:

public class WeatherForecast

{
     public WeatherForecast()
     {
         this.Forecast = new List<ForecastEntry>();
     }
     public string City { get; set; }
    public string State { get; set; }
    public string Result { get; set; }
    public List<ForecastEntry> Forecast { get; private set; } }

And the XAML for the whole forecast:

<Grid d:DataContext="{Binding Source={d:DesignInstance Type=data:DesignForecast, IsDesignTimeCreatable=True}}">
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="Auto"/>
         <RowDefinition Height="*"/>
     </Grid.RowDefinitions>
     <StackPanel Orientation="Horizontal" Margin="10">
         <TextBlock Text="{Binding City}" Style="{StaticResource HeaderTextStyle}"/>
         <TextBlock Text="," Style="{StaticResource HeaderTextStyle}"/>
         <TextBlock Text="{Binding State}" Style="{StaticResource HeaderTextStyle}" Margin="20 0 0 0"/>
     </StackPanel>
     <TextBlock Grid.Row="1"
                 Text="{Binding Result}"
                 Style="{StaticResource PageSubheaderTextStyle}"
                Margin="10"/>
     <GridView Grid.Row="2" ItemsSource="{Binding Forecast}">
         <GridView.ItemTemplate>
             <DataTemplate>
                 <local:ForecastEntry/>
             </DataTemplate>
         </GridView.ItemTemplate>
         <GridView.ItemsPanel>
             <ItemsPanelTemplate>
                 <WrapGrid MaximumRowsOrColumns="1"/>
             </ItemsPanelTemplate>
         </GridView.ItemsPanel>
     </GridView>
 </Grid>

The design-time model for the forecast is kind enough to offer some variety and generate several days of entries.

public class DesignForecast : WeatherForecast

{
     private readonly Uri[] testUris = new[]
      {
new Uri("http://ws.cdyne.com/WeatherWS/Images/mostlycloudy.gif",
                   UriKind.Absolute),
new Uri(http://ws.cdyne.com/WeatherWS/Images/sunny.gif,
UriKind.Absolute)
        };
     public DesignForecast()
     {
         this.City = "Woodstock";
         this.State = "GA";
         this.Result = "Design-mode data";
for (var x = 0; x < 7; x++)
         {
             var offset = 7 - x;
             var entry = new ForecastEntry
             {
                 Day = DateTime.Now.AddDays(-1 * offset),
                 ForecastUri = this.testUris[x % 2],
                 Description = string.Format("Rainy {0}", x),
                 PrecipitationDay = "50",
                 PrecipitationNight = "20",
                 TemperatureLow = "25",
                 TemperatureHigh = "49",
                 TypeId = x
             };
             this.Forecast.Add(entry);
         }
     } }

And this is what I see in the designer:

weatherforecast

How cool is that? Now I have what I need. The view model exposes a zip code for the user to enter and an instance of the forecast. The view model I instantiate directly but in the constructor detect design mode and set the forecast property to a design version:

if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)

{
     this.currentForecast = new DesignForecast();
     this.zipCode = "30189";
     return; }
(Here’s a tip – I usually set the field values in design mode so the property change notification isn’t fired – when it’s done in the constructor it will be there in time for binding to the design view).

Now I have the whole app assembled, and even with a “real” instance of the view model in the designer, I’m able to see what the app will look like.

weatherdesigner 

The individual design instances let me compose the UI with design-time data, while the view model can then instantiate a design instance or “go live” and actually call the service to provide a “real” weather forecast. Here’s what the runtime looks like … not too much different from the design-time view!

runtime

Thank goodness for XAML and the ability to easily create design-time data for our apps.

Thursday, February 28, 2013

Windows Store Apps, SVG, and HTML Interoperability

There are several reasons you may wish to show HTML content in your Windows Store app. You may have information that is updated frequently and makes the most sense to consume as HTML data. Your app may aggregate feeds that contain HTML content. In some cases you may be creating a native client that accesses an existing web-based application that you need to interoperate with. Fortunately, the WinRT has a control that addresses these needs: the WebView control.

It is important to understand what the purpose of the control is and how that may impact how you architect your app. The control itself is not intended to be a complete replacement for a browser. Indeed, Microsoft has made it clear that if you try to get an app approved in the store that tries to solely interact with a web-based app or simply act as a web browser, it will be rejected [1-Ten Things You Need to Know about WebView]. There are several limitations built into the control that prevents many scenarios.

The control uses the Internet Explorer 10 engine. It does not support advanced features in HTML5 including caching, indexed databases, programmatic access to the clipboard, or geo location. It supports the same version of the Document Object Model (DOM) that is used by Windows Store apps written in JavaScript [2 - Document Object Model (DOM) (Windows)]. There is no support for any type of plug-in or ActiveX extension, including Flash, Silverlight, or embedded PDF documents.

There is full support for enhanced protocol handling [3 - Auto-launching with file and URI associations]. This provides support for things like custom protocols that allow you to access resources embedded in your app as well as links that will automatically launch the program associated with them. You can generate a web page that, when viewed, not only provides content served from within your app, but also allows the user to open those resources using their preferred app (for example, a resource with a .pdf extension will open with the preferred reader app).

The control is also unique because it cannot be covered by other controls. It completely takes over the pixels defined for its area. Any controls that you attempt to place in front of the WebView control will be cropped. If you must overlay the page with controls, you can capture the current view using a special WebViewBrush and use that brush to render a surface.

The final and perhaps most important feature of the WebView control is the ability to interoperate with your Windows Store app. Your app can communicate with the web page by invoking JavaScript functions and passing in parameters. The page can also interact with your app by calling a method on an object that WinRT creates in the DOM. This allows you to create some truly interactive experiences between web content and your Windows Store app.

The WebViewExamples project contains several examples of working with HTML and JavaScript. MainPage.xaml defines a WebView control named WebViewControl and a brush named WebBrush. When the page is loaded, a handler is registered to the LoadCompleted event on the WebView. This will fire any time a new resource (whether it is a string literal or a web page) is loaded. It will force the brush to refresh and show a dialog indicating the content that was loaded.

private async void WebViewControlLoadCompleted(object sender, NavigationEventArgs e)
{     
WebBrush.Redraw();
     var url = e.Uri != null ? e.Uri.ToString() : "Text Content";
     var popup = new MessageDialog(url, "Content Loaded.");
     await popup.ShowAsync();

}

The first button triggers a straightforward page load.

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
     this.WebViewControl.Navigate(new Uri(JeremyBlog)); }

The page is my main blog page. You’ll find it loads and renders fine. You can also click on links and navigate just as if you pulled the page up in a web browser. There are no forward or backwards buttons and there is no place to enter a new address so you are stuck following the links provided by the control. Notice that the dialog fires every time you navigate to a new page – you could easily use this feature to inspect where the user ended up and hide the control or reset it if needed.

The second button invokes a specific page as a mobile client by writing a user agent that mimics an iPhone. My blog will detect that a mobile device is accessing the page and redirect to a mobile-friendly page. In this mode you may see several errors thrown by the debugger. This is because the WebView control will throw an error any time it encounters a JavaScript error or an issue parsing the DOM. You can turn off the JavaScript errors by going into the debugger settings and un-checking Script under the Just-In-Time tab. Other errors you have to muscle through and just select No – on my machine the mobile page generates four errors I must acknowledge before accessing the page. If you run the app outside of the debugger, it will swallow these errors and run normally.

The only way to update the user agent that the WebView control uses is to use some hacks that will prevent your app from making it into the app store. For those hackers in the audience, you’ll need to p/Invoke urlmon.dll and call UrlMkSetSessionOption with option 0x10000001 and your user agent string prior to navigating with the control. A more direct approach is to download the page yourself and pass it to the control as text. The steps are shown below.

private async void ViewMobile_OnClick(object sender, RoutedEventArgs e)
{
     var handler = new HttpClientHandler { AllowAutoRedirect = true };
     var client = new HttpClient(handler);
     client.DefaultRequestHeaders.Add("user-agent", MobileUserAgent);
     var response = await client.GetAsync(new Uri(JeremyYogaPost));   
response.EnsureSuccessStatusCode();
     var html = await response.Content.ReadAsStringAsync();
this.WebViewControl.NavigateToString(html);
}

The example sets up a client that accepts redirects (in the case of the blog post reference, it will redirect to a mobile version), then creates a client and sets the user agent to mimic a mobile device. The page is requested and the code ensures a successful response was obtained before loading the content of the response and sending it to the WebView control.

This technique is common for requesting content in a format that is suitable for viewing within your app (mobile content tends to have less chrome so it is easier to process). You can also parse and analyze the content prior to presenting it to the end user. This allows you to strip unwanted tags or even inject your own JavaScript and content as needed prior to the page being displayed.

In some apps you may wish to include embedded HTML resources for your apps to display. The third button demonstrates this technique. It also shows that the rendering engine has full support for Scalable Vector Graphics (SVG) [4 - W3C SVG Working Group], which can be useful if you need to integrate charts or vector-based graphics in your application and have existing implementations using SVG. In the example app, there is an embedded HTML file named Ellipse.html in the Data folder.

Referencing this resource is simple and straightforward. The special ms-appx-web protocol provides a path to the WebView control that is embedded in the store app. You’ll notice it uses three forward slashes and then provides a path to the resource in the app from the root.

private void ViewSvg_OnClick(object sender, RoutedEventArgs e)
{
     this.WebViewControl.Navigate(new
          Uri("ms-appx-web:///Data/Ellipse.html")); }

You can also embed static text (or dynamic text that you build and generate prior to passing into the control). The fourth button triggers the load of a string literal. The literal contains the text for an HTML document and includes various header tags, an embedded image (the logo of the app itself), and a hyperlink that demonstrates you can navigate to embedded content or external content. If you follow the link to the external website, you’ll see that the base URL is consistently reported as static text because that’s how the original document was loaded.

private void ViewString_OnClick(object sender, RoutedEventArgs e)
{
     this.WebViewControl.NavigateToString(HtmlFragment); }

The final button demonstrates how your app can interoperate with the web. To show this, I included a JavaScript function in the template of my blog. The function is just a few lines of code. If you load any page from my blog and view the source, you can search for “supersecret” to locate the function:

function superSecretBiographyFunction(subPath) {
   window.location.href="http://csharperimage.jeremylikness.com/" + subPath;
}

The function is usually not called, but that will change if you load one of the blog pages using the example app and click the last button. The code snippet below shows the implementation. The InvokeScript method is used to call the function. You can pass in null for a function that takes no parameters, otherwise you can pass in an array of values. In this case the path to my biography is passed in, and the page picks it up and navigates to the path. Note that you can call JavaScript on any type of page the control rendered, including embedded resources or literals you’ve passed in.

private async void CallJavaScript_OnClick(object sender, RoutedEventArgs e)
{
     MessageDialog popup = null;
     var parameters = new[]
                          {
                                 "p/biography.html"
                          };
     try 
{
        this.WebViewControl
.InvokeScript("superSecretBiographyFunction", parameters);
    }
    catch (Exception ex)
     {
        popup = new MessageDialog(ex.Message, "Unable to Call JavaScript.");
     }
     if (popup != null)
     {
         await popup.ShowAsync();
     } }

An attempt to invoke a function on page that doesn’t have that function will result in an exception. The code captures the very user-unfriendly exception and displays it for you. The pattern is important to note because it is not possible to use the await keyword from within a catch block. The workaround is to capture any necessary information needed in the catch, then await the dialog to display the information once the block is exited.

Although sending information to a page is nice, wouldn’t it be great if you could receive information back? This scenario is possible and you can in fact create apps that have two-way conversations with web pages. If you searched for the source snippet above, you may have also noticed this block of code:

if (document.title==='C#er : IMage: Synchronous to Asynchronous Explained') {
if ((typeof (window.external) !== "undefined") && (typeof (window.external.notify) !== "undefined")) {
      window.external.notify(new Date().toLocaleString());
   }
}

I would not normally do a string comparison against a topic title to trigger application logic, but I can get away with it here because I own the blog and am not planning on changing the title. When the user navigates to a specific topic inside a WebView control, the web page itself will actually send a message to the Windows Store app that contains the localized date and time. The communication between the web page and the Windows Store app is illustrated here:

htmlwinstoreinterop

The function first checks for the existence of the window.external object. This is provided to the JavaScript runtime by Internet Explorer to provide access to the object model of the host [5 - External object (Internet Explorer)] (in this case, the host is the WebView control). The control in turn exposes the notify method to the runtime. A call to this from the web page with a single string parameter will raise the ScriptNotify event on the WebView control.

The example app simple stores the value that is passed to a local variable.

private void WebViewControlScriptNotify(object sender, 
Windows.UI.Xaml.Controls.NotifyEventArgs e) {
     this.message = e.Value; }

Once the entire web page is loaded, the LoadCompleted event checks for this value and displays it when present.

if (string.IsNullOrEmpty(this.message))
{
     return; } popup = new MessageDialog(
     this.message,
      "The Blog Has Spoken!"); this.message = string.Empty; await popup.ShowAsync();

To see this in action, use the timeline on the right side of my blog to navigate to the year 2012, the month August, and the title “Synchronous to Asynchronous Explained.” The result should be two pop-ups, one to notify you when the page has loaded and a second that declares the blog has spoken and displays the date. This closes the loop and demonstrates how Windows Store apps can load, display, and interact with HTML-based content.

This post just scratches the surface of what is possible but hopefully provides you with an in-depth demonstration of how you can embed HTML, SVG, and even JavaScript in your Windows Store apps.

Full Source Code

Side-Load Package