Andrej Tozon's blog

In the Attic

NAVIGATION - SEARCH

Windows 8 Metro-style application manifest

When you create a new Windows Metro style application, Visual Studio will automatically create the application manifest for you. The file will be called Package.appxmanifest and will be included in the root of the project. Looking at it closer reveals that it’s a plain XML file that can be generated manually or with the help of some other tool as well.

Visual Studio, however, offers a nice GUI editor for editing the application manifest file. This is a quick walk through its tab pages. To invoke the editor, simply double-click on the manifest file or choose Store | Edit App Manifest from the menu.

Application UI

image

The tab for application menu hosts the basic info about your application.

Display Name is the title of your application. It will appear on the start screen, search page, etc., wherever the user can see. It can be localized.

Entry Point should point to the application’s activatable class id. It should be set to project’s App class, but in current build of Visual Studio, changing it to invalid value doesn’t currently seem to affect anything.

Description contains a longer description of your application, but it shouldn’t exceed 2048 characters. It can be localized as well.

Tiles (Logo, Wide Logo and Small Logo) represent the graphics you want to present your application with. The logo is also used as the main tile and the Small Logo is used for lists, etc. The Wide Logo is used when the app requires the wide format tile. Valid format for all graphics are .png and .jpg.

Further down, there are even more options…

image

Show Name and Short Name work in together with the above Display Name. Setting Show Name to Yes and leaving Short Name empty, the Display Name will be displayed on the application tile as an overlay. Set Short name to a custom name and Short Name will be displayed as the overlay.

Foreground Text sets the color of the text displayed on the application tile. In can be set to Light or Dark, for  best fit with the tile graphics.

Background Color specifies the tile’s background color. Can be either named or the ‘#’ color.

Notifications control how the notifications look and work.

Badge Logo points to the graphics that will be displayed on the lock screen as a notification from your application.

Lock Screen Notifications specify what kind of notifications your application will support when the system is locked. Can be set to Tile Text, Badge or both.

Toast Capable should be set to true when you want to send alerts from your application.

Splash Screen options (Splash Screen and Background Color) control the appearance of the splash screen. Splash Screen should point to the splash screen graphics and Background Color specifies the background color for that screen (transparency effects).

Initial Rotation specifies the initial rotation when the application starts. Can be set to all four possible rotations (Portrait, Landscape, Portrait and Flipped, Landscape and Flipped.

Capabilities

The next tab in application manifest editor allows you to set the protected resources you want to allow your application to access. Your application will not have the access to those capabilities if you don’t explicitly set them here, nor they won’t be accessible in cases when hardware does not support it, are blocked through other security policies, or when explicitly denied access by the user herself. Note that the user is prompted about those capability requirements when she is installing your application and can deny those requests. Even later…

Here’s the current list of those capabilities:

image

Declarations

Declarations are your application’s extensibility points, for better integration with the system and/or other installed applications. Some of those extensibility points include:

  • Contact Picker (your application serves as a contact picker for other applications),
  • File Type Associations (registers your app as a (default) handler for a specific file type),
  • File Picker (your app serves as a content picker for other apps; think choosers in Windows Phone),
  • Protocol (your app registers as a URL Protocol handler),
  • Search (provides searching functionality),
  • ShareTarget (for your next social networking application Smile),

… and a few more. All declarations have their own options and settings.

image

Packaging

The Packaging tab holds the info, relevant to deploying and publishing your application.

image

Package Name uniquely identifies the package and therefore your application too. It’s a GUID.

Package Display Name is a localizable package title that is displayed to the users.

Logo points to the application store logo.

Publisher describes the application publisher and matches the publisher subject information from the certificate that is used for signing the application manifest. The value is set automatically when choosing an existing certificate or create a new test certificate.

Publisher Display Name and Package Family Name are also derived from the chosen certificate. Publisher Display Name can be changed and even localized.



Windows 8 applications and JSON data

For anyone that wants to call various JSON data service endpoints in a Windows 8 (Metro style?) application, there’s a couple of changes in “.NET APIs for Metro style apps” (using MSDN terminology here) that needs to be looked into. For this blog post I’m using flickr API as an example of how to fetch and parse JSON data.

Where’s my WebClient?

No, there is no WebClient class in the new API. But…

There’s a HttpClient class that works similar, or even better, by providing an asynchronous method to fetch data. If you’ve looked into the Async CTP bits, the new method should look very familiar.

The new HttpClient class itself resides into the System.Net.Http namespace. Jumping right into the code:

public async Task<string> GetPhotosStream()
{
    HttpClient client = new HttpClient();
    string url = "http://www.flickr.com/services/rest/?method=flickr.photos.search&format=json&nojsoncallback=1&api_key=<yourkey>&text=buildwindows";
    HttpResponseMessage response = await client.GetAsync(url);
    return response.Content.ReadAsString();
}

Shall anyone need it, there is also a synchronous method called Get() that will block until full response message is returned and read on the client.

Other than Get(Async), there are three method pairs more – Get(Async), together with Put(Async), Post(Async) and Delete(Async) forms the full set of verbs supported by REST (Representational state transfer) to manipulate data.

GetAsync() will return a HttpResponseMessage, which contains the returned status code, response headers and returned content, which can be read in a variety of ways.

Parsing JSON

I have rarely used native framework JSON classes (I prefer using JSON.Net), but looking at the new API it looks like there’s quite a few changes here as well.

A returned string can be fed to the JsonObject in its constructor or using Parse() method on its instance. Either way will result in an exception if the JSON string is invalid and couldn’t be parsed.

Once parsed, you’ve got full access to it’s structure. Before I show the code to access it, let’s look at snippet of the returned JSON string:

{
  "photos":
  {
    "page":1, 
    "pages":1, 
    "perpage":100, 
    "total":"13", 
    "photo":
    [
      {"id":"6146549133", ..., "title":"20 Microsoft interns (three from Olin) at this week's BUILD conference", ...},
      {"id":"6146244616", ..., "title":"Internet Explorer", ...},
      ...
      ...
    ]
  },
  "stat":"ok"
}

And this is how you would read the titles of returned photos:

private static List<string> titles = new List<string>();

public static async void ExaminePhotos()
{
    string responseText = await GetPhotosStream();
    JsonObject root = new JsonObject(responseText);
    bool isSuccess = root.GetNamedString("stat") == "ok";
    JsonObject info = root.GetNamedObject("photos");
    int page = (int)info.GetNamedNumber("page");
    int totalPages = (int)info.GetNamedNumber("pages");
    JsonArray photos = info.GetNamedArray("photo");
    for (uint i = 0; i < photos.Count; i++)
    {
        string title = photos.GetObjectAt(i).GetNamedString("title");
        titles.Add(title);
    }
}

While the “Named*" methods return typed values (GetNamedString() returns a string, GetNamedNumber() a double, etc.), it’s also possible to get the JSON value by string indexer and later call to its typed value, e.g. json[“stat”].GetString(), which gets useful if you want to check for its type first.

The second part deals with a JsonArray named photo, which gets enumerated and read in a similar manner.

Wait, isn’t this supposed to be simpler?

Of course, the DataContractJsonSerializer is still here. In fact, it appears to be the same class, just moved into a separate assembly.

To use it, create appropriate classes from the JSON structure (one of utilities that can help) and deserialize JSON string with the help of DataContractJsonSerializer:

string responseText = await GetPhotosStream();

DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(RootObject));
RootObject root;
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(responseText)))
{
    root = serializer.ReadObject(stream) as RootObject;
}

The result is a full object tree that was deserialized from the flickr API JSON string.



First look at Windows 8 application as a developer

It’s been a couple of days since I installed the //build/ preview version of Windows 8 and in this short time I’ve grown to quite like it. It’s an interesting mix of the new Metro style and the “old” Windows 7-like style.

There were two things I’ve just had to install though, to make my life easier while working with Windows 8. The first thing was Total Commander, a file navigation alternative to Windows Explorer, and shortly after that, I installed “Mouse without borders”, the software KVM-like solution that lets you control multiple computers with a single set of keyboard and mouse, share clipboard etc. (for that I had to manually install .NET Framework 2.0 first, though).

The most confusing part about Windows 8 was the mixture of touch and mouse input. I installed Windows 8 on a touch-enabled notebook and was surprised that I could pan, zoom and drag things around, but couldn’t select apps. Tiles responded to tap, but apps just didn’t start and I had to use the mouse to click on them. I’m blaming the missing/incomplete drivers for that and expect it to be fixed by the time Windows 8 gets released. Once I got comfortable working around those issues, I started exploring the new Metro UI, mostly exploring my options for creating my own Metro application.

I took the default Weather application as the example. Funny thing is that at first I couldn’t find a way to change the temperature display to show Celsius instead of Fahrenheit. I started the app and started clicking all over it and eventually found out that right clicking anywhere on the screen (a Metro application takes up the whole screen unless it shares that space with other apps) brings up the Application bar (in touch world, the app bar is displayed by swiping up your finger from the bottom of screen).

image

Application bar

Similar to Windows Phone, Application bar is reserved for command and status buttons. One difference is that buttons are aligned to left and right edges instead of centered horizontally. This makes them easier to reach by your thumb fingers when holding a tablet.

Application bar hosts your command buttons that may change depending on the context - the state your application is in. You can also choose to include more system level commands such as the option to pin the application to the Start screen. Buttons you shouldn’t include in the Application bar are the ones for displaying application's settings and / or search pages. More on that later.

While application bar revealed some helpful options, there was no settings button to be found. Running around with the mouse I found a hot-spot on the bottom-left of the screen (where you’d expect the Start button to be on older Windows). Dragging my mouse to that corner revealed a Start-like menu with the “charm” options: Settings, Devices, Share, Search and Start (in touch world, charms are displayed when you swipe from the right edge towards center).

image   image

Great! Settings!

Settings and preferences

Turned out that settings charm took me to the settings pane that appeared on the right-hand side of the screen, offering me the following options:

  • Rate and Review the application (doesn’t currently work because Windows Store is not available yet),
  • Control system access for Weather (allows user to enable or disable the capabilities required by your application),
  • Weather preferences. That last one was key and the most difficult to find because it looked like some kind of group header. When I discovered that it was selectable, I got into the preferences page that allowed me to change application’s preferences.

image image

Preferences is also one of the custom Settings pages you can implement in your own application. There are a few settings commands you can add to the Settings pane that you map to specific pages, some of those being the About page, Preferences, Help and Privacy statement. From what I found out, only for Settings commands can be displayed in the Settings pane at once, but I’m not sure if that can change depending on your display resolution.

image

You don't need to worry when and how the Settings pane will be displayed, that all is handled by the OS, which means some less work for the developer and, perhaps more importantly, a unified experience across all Metro applications. You only need to implement the way Setting commands display application-specific pages (Preferences, About, etc.)

Search and Share


Search and Sharing contracts are implemented similar to Settings, but go additional step forward. If your application is going to support searching, you can hook up a Search pane, implement required event handlers and provide a custom results page. For Sharing, that would mean to implement the sharing logic. It looks like all application can share their screenshot by default (even if you don’t implement the sharing contract).

image    image

One bonus that Search and Sharing contract provide over Settings is that other applications can use your application as a search or share target. That means that from whichever other application user is currently using, she can search your application (or share her content through it) just by choosing it as a target from her current Search (or Share) pane.

There seems to be quite a few system hooks in Windows 8 that your Metro apps can connect to. Those mentioned above only happen to be the most exposed and accessible in the short run. Clearly it will take some time to get fully familiar with the new Runtime and OS integration and let’s not forget, we’re playing with the preview bits – anything can change in future versions.



Windows 8 geolocation API: First run

Microsoft Windows 8 OS was finally revealed this week at Microsoft’s //build/ conference. It looks like a promising OS, with Metro style theme showing all over it.

image

If you want to install it, look it up on the MSDN subscriptions site or head over here (limited set of SKUs). If you’re a developer, pick the one that includes the Visual Studio 11 Developer preview (or install tools – available also as a separate download – later).

A lot is about to be said of WinRT, the new Windows Runtime and how it relates to .NET and how developing Windows applications will going to be (dis)similar to developing WPF or Silverlight applications. Skipping that discussion for later, I jumped right into developing tools to see how familiar the new API would look to me and whether my past experience with developing XAML based applications in the past few years would help or not.

Starting with the geolocation API

Having developed a couple of Windows Phone application that used my location as a crucial piece of information, I was curious how the same would be done in a Windows 8 application. I’m posting this as a walkthrough (assuming you installed the Visual Studio 11 Express for Windows Developer Preview):

[A short note before you start: the following is based on the //build/ Developer Preview bits and will most likely change in future versions]

1. Open Visual Studio 11 Express.

2. Create a New Project. A few project templates are available, but let’s start simple and choose a basic C# Application.

image

3. If you’re a XAML developer, you’ll find yourself into a very familiar environment. A big plus on that is that Window designer is loading in the background and not blocking you to fiddle with other things while it loads [yes!]

image

[I’ll look into various settings to control you application’s look and feel in one of my future posts]

4. Similarly to Windows Phone, using a location requires you as a developer, to explicitly declare that your application will require access to the location API. This is set in the application manifest. In a Solution explorer, look for Package.appmanifest item and double click on it to open – the manifest properties window will open.

5. Click on the Capabilities tab. Uncheck the Internet (Client) capability and check Location capability (just under it).

image

You’ve just declared that the application will require the Location capability. Had you not enabled this item, anything access to the location API in the application would have no effect. No errors or exceptions would bi risen, it just wouldn’t work.

6. Go back to the MainPage.Xaml and add a TextBlock named Status into the main Grid (LayoutRoot). This is where you’re going to display the current location.

7. Switch to the code view (quick heads up: the F7 keyboard shortcut is not a default for this one anymore).

8. The core class you’re going to use is called Geolocator. It’s very similar to GeoCoordinateWatcher class from Windows Phone, so working with it should be fairly familiar:

public sealed class Geolocator : IGeolocator
{
  public Geolocator();
  public PositionAccuracy DesiredAccuracy { get; set; }
  public PositionStatus LocationStatus { get; }
  public double MovementThreshold { get; set; }
  public uint ReportInterval { get; set; }

  public event TypedEventHandler<Geolocator, PositionChangedEventArgs> PositionChanged;
  public event TypedEventHandler<Geolocator, StatusChangedEventArgs> StatusChanged;
  public GetGeopositionOperation GetGeopositionAsync();
}

Similar to GeoCoordinateWatcher, it has

  • DesiredAccuracy (Default, High),
  • LocationStatus (Ready, Initializing, NoData, Disabled, NotInitialized, NotAvailable) – with two new values,
  • MovementTreshold,
  • PositionChanged and StatusChanged events,

New in Geolocator are:

  • ReportInterval – the requested minimum time interval between location updates,
  • GetGeopositionAsync() – single call method for asynchronous request for location data.

Noticed the TypedEventHandler event declarations above? What are those? Let’s continue with the example…

9. Set up the Loaded event handler and paste the following code into it:

Geolocator locator = new Geolocator();
locator.PositionChanged +=
new TypedEventHandler<Geolocator, PositionChangedEventArgs>(OnPositionChanged);

OnPositionChanged event handler signature is as follows:

void OnPositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
}

To reflect the TypedEventHandler, you can see that sender is no more a plain object, it’s typed! That means no more unnecessary casting and your code is a tad more error-prone.

10. PositionChangedEventArgs holds a reference to a Geoposition, which is declared as:

public sealed class Geoposition : IGeoposition
{
    public CivicAddress CivicAddress { get; }
    public Geocoordinate Coordinate { get; }
}

While Geocoordinate is similar to GeoCoordinate from Windows Phone (Latitude, Longitude, Altitude, Speed, Heading, Accuracy, etc.), the CivicAddress should contain address data, associated with the reported Geocoordinate. I’m saying “should” because from all address properties (City, Country, PostalCode, State) for my current location (Ljubljana, Slovenia), the API only returns my country code (SI). I’m interested to hear how the same API behaves in other locations around the world so if you’re using it, please let me know.

11. If you try setting the Status label text in the OnPositionChanged event handler, you’ll get the invalid cross-thread exception and that’s because the event gets kicked on the background thread. In order to set the text, you have to invoke that on the UI thread, using the dispatcher. This is the part where things seems to differ the most. There’s a new dispatcher called CoreDispatcher. Declare it on the class level and set to page’s Dispatcher property in page’s constructor. That will guarantee you you can use it from the background thread.

So here’s the full MainPage code:

partial class MainPage
{
    CoreDispatcher dispatcher;

    public MainPage()
    {
        InitializeComponent();
        dispatcher = Dispatcher;
        Loaded += new RoutedEventHandler(OnLoaded);
    }

    void OnLoaded(object sender, RoutedEventArgs e)
    {
        Geolocator locator = new Geolocator();
        locator.PositionChanged += 
            new TypedEventHandler<Geolocator, PositionChangedEventArgs>(OnPositionChanged);
    }

    void OnPositionChanged(Geolocator sender, PositionChangedEventArgs args)
    {
        dispatcher.InvokeAsync(CoreDispatcherPriority.Normal, DisplayLocation, this, args);
    }

    void DisplayLocation(object sender, InvokedHandlerArgs e)
    {
        IPositionChangedEventArgs args = e.Context as IPositionChangedEventArgs;
        Status.Text = string.Format("Country:{0} Lat: {1} Lng: {2}", 
            args.Position.CivicAddress.Country, args.Position.Coordinate.Latitude, 
            args.Position.Coordinate.Longitude);
    }
}

12. You can simplify the InvokeAsync code by using a lambda expression, though it may be a bit harder to read and/or debug:

void OnPositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
    dispatcher.InvokeAsync(CoreDispatcherPriority.Normal,
        (s, a) =>
        {
            Status.Text = string.Format("Country:{0} Lat: {1} Lng: {2}", 
                args.Position.CivicAddress.Country, 
                args.Position.Coordinate.Latitude, 
                args.Position.Coordinate.Longitude);
        }
        , this, args);
}

13. Now try to run the project. This is what you should see:

image

Windows is asking you if this application can use your Location. If user chooses Block, application��s request to access the location is denied. No errors or exceptions would be thrown, it just wouldn’t work. If user allows the access, the app will work as expected.

Note: the user can change this permission any time through the Settings charm: When application is running, move your mouse to the bottom left corner – the menu, similar to start screen should appear.

image

Click Settings and notice the right side bar. Click on the “Control system access for [YourAppName]” – you can change the access settings from there

image         image

If you want to test for access availability status from within the app, check Geolocator’s LocationStatus. In case the location access is disabled, it should be set to NotInitialized (although I expected Disabled).

Another fun fact is that Geolocator is not initialized on it’s instantiation, but only when you actually do something with it. In this case, it initializes when you subscribe to the PositionChanged event. This is also the same code line that will cause application (or Windows RunTime) to pop up that permissions dialog from above. After that line, the LocationStatus should be set to a valid status (Ready if access to location is enabled and NotInitialized if it’s not).

Note: Windows will only ask you for permission the first time it’s required. After that, it’s on user to change this permission. But if you want to test this, go to the Application manifest, Capabilities tab, and re-check the Location capability – that should reset the prompt.

But we’re not done yet.

Subscribing to PositionChanged event will ensure the event handler will be called each time Position is “changed” (that actually depends on your Geolocator’s MovementTreshold and ReportInterval property settings). To stop listening to position changes, you can simply unsubscribe from the PositionChanged event.

But… In a lot of cases, we only want to determine the current location once, instead of continuously tracking it. Fortunately, GetGeopositionAsync method does just that – retrieves the current position and it does it in the asynchronous manner (as suggested by Async method suffix by proposed convention).

And guess what? Async methods are unbelievable easy to handle with the new async / await keyword pair. Let’s give it a try.

14. Change the OnLoaded event handler too look like this:

async void OnLoaded(object sender, RoutedEventArgs e)
{
    Geolocator locator = new Geolocator();
    Geoposition position = await locator.GetGeopositionAsync();
    Status.Text = string.Format("Country:{0} Lat: {1} Lng: {2}",
        position.CivicAddress.Country, 
        position.Coordinate.Latitude, 
        position.Coordinate.Longitude);
}

Geolocator is instantiated as before, but the current position is accessed through the GetGeoPositionAsync() method. And notice how that method is decorated with the await keyword and the whole OnLoaded method with async. The principle will also guarantee you that your code, after that async call, can safely call into the UI thread. No dispatcher needed. And from what I know, there are many async method scattered around the new runtime, it will just make coding so much easier, not to mention the new responsive UI.

Wrapping up

That’s it! My first experience with the new API. So far I love it but porting existing and building new applications will eventually show its real value.

And to just briefly touch on the current hot topic – I really think that desktop application development has just shifted gears, although it’ll take some time to lift off the ground. What we’re looking at is an early preview and it will take some time till release, and event more to a broad Windows 8 adoption.

If you have any comments, questions, suggestions for future posts on the subject, any feedback at all, do not hesitate to contact me.



Bikes, a Windows Phone application for bike sharing systems

My latest Windows Phone application found its way to the Microsoft marketplace.

Bikes is designed to help bicyclists that use city bicycle sharing systems across Europe to find nearest stations, provide some basic info about available bikes and free parking slots for each of those stations.

Here’s a short video:

[Short note: the video about shows how the next version will look like (v1.0.1), current marketplace version is v1.0.0]

The main purpose I’ve decided to create this app was to support the new bicycle sharing system in my city (started May this year), but since the same system is use in other (mostly) European cities as well, I added some of those as well. I’m planning to support other systems and adding more cities in future releases.

You can follow the following twitter account – bikeswp7 – for latest news regarding the app, send suggestions, bug reports and any comments you have.

You can download application directly from the marketplace. If you can’t access the Marketplace link with your desktop browser, here’s another link.



Localizing the August 2011 Windows Phone Toolkit

Great news! A new version of Windows Phone Toolkit was released today. These bits target the “Mango” OS (which translates to SDK v7.1). The “pre-Mango” version (7.0) will follow in a short-while.

Download the Toolkit from Codeplex. Available also on NuGet.

One of the new features coming with this release is localization support. Localized strings are there mostly to support brand new Date and Time converters, but they also include a few strings used by Date and Time picker controls that were available in the previous release.

The strings are localized to 22 languages that are the languages, available the “Mango” OS. Chances are you’re going to be writing an application localized to a “non-Mango” language (yes, there are us who are still waiting!), so here’s a tip how to extend the toolkit localization features to your “unsupported” language. I’ll be using the Slovenian (my native) language as the example.

1. Download the toolkit binaries and source code from Codeplex:

2. Unzip the source code package and open the solution (PhoneToolkit.sln).

3. In Solution Explorer, locate the LocalizedResources folder. Copy the neutral language (US English) control resources file and rename it by appending target culture code to the filename (sl-SI is for Slovenian language):

loc1

4. Open the new ControlResources file by double clicking on it in Solution Explorer. Managed Resources Editor should appear, listing original strings.

5. Take some time and translate all strings into the target language. It will probably take an iteration or two to get it right (have to test it in a real case example). In case of Slovenian language, there’s also a slight problem with missing dual  forms (e.g. there are singular and plural, like 1 hour and >1 hours, but I can’t specify the string for 2 hours), plus some other language specifics I have yet to figure out how to work around them.

loc2

6. Build the project. It should compile (make sure you’re using tools for v7.1).

7. Go to the Bin\Debug folder (or Bin\Release, depending on your build configuration) and locate the sl-SI folder (or the one that matches your culture code). In it, there should be a Microsoft.Phone.Controls.Toolkit.resources.dll file. Copy folder to the safe place on your disk. You’ll need it whenever you start a new project leveraging the Windows Phone Toolkit..

8. You’re done with the Toolkit. Start a new Windows Phone project, add a reference to the new Toolkit, add resource files, etc., and start developing your localized application.

9. Because you’re targeting the unsupported language, don’t forget to add the following line to the application start:

Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

That’s usually the first line in my App constructor. The other usual localization steps apply: Edit .csproj file to add supported cultures, set the neutral language, …

10. After building your application, you’ve got the application package (.Xap file). Before deploying it on your device or marketplace, copy the culture-specific folder containing the new localized dll (from step 7) into it. If you’ve chosen English as the neutral language, the folder with your culture code (sl-SI in my case) should already be in place.

Note: I didn’t have to change the AppManifest.xml file in Xap to include the new localized resource dll, but perhaps it’s a good idea to do so. You may also choose a more convenient method of including the resource file at design time to avoid file copying and changing the manifest file after each build.

11. That’s it! With localized resource file in place, your application should now display Toolkit’s resources in your own language.

loc3

This is a screen shot from the Sample application that comes with the new Toolkit.



On a path to a generic About page

Since every Windows Phone application should have some kind of About page, I wanted to see if I could build a generic page that I would reuse in my other apps. These are a few tips I picked up during building such a page:

1. The About page is rarely accessed so I put it in a separate assembly. This way I took some initial load off the main assembly and the About assembly can now easily be shared with other apps.

2. If you want to display the application icon on your About page, there is no need to create new graphics. Depending on your target size, you can choose from either ApplicationIcon.png (62x62) or Background.png (173x173) icons. To put the icon on your About page, use:

<Image Source="/ApplicationIcon.png" Stretch="None" />

And of course you can specify your own size and adjust the stretching attribute.

But don’t worry about the ApplicationIcon.png not being included in the About page project. With application icons being marked as Content, the contents of a Xap should look something like this:

image

By specifying an external link reference to the ApplicationIcon.png, the icon will be displayed regardless of it not being part of the project that contains it.

3. Static text. This includes titles, labels and text that will likely be the same across every application. If you’re not localizing your apps, you may as be well hard-coding strings into your XAML. But if you are, you would most definitely want to pull them from your resource files. In latter case, the standard localization guidelines apply. Again, don’t worry if your if your localization files are in your main assembly. The application will pick them up correctly regardless (even at design time).

<TextBlock x:Name="PageTitle" 
           Text="{Binding Strings.AboutTitle, 
                  Source={StaticResource LanguageResources}}" 
           Margin="9,-7,0,0" 
           Style="{StaticResource PhoneTextTitle1Style}"/>

4. Dynamic text. This includes the version number, application title and other text that will be unique to every application or its version. Some of these texts could be stored in resource files as well, but let’s look at the alternative options.

If you take a look at the AssemblyInfo.cs file of your main project (you’ll find it in the Properties folder), you’ll see it’s populated with some weird assembly attributes you don’t even care about (that’s because you’re setting and changing them from Visual Studio’s dedicated project properties page, but that’s not the point).
The point is that you can access all of these strings from code. All you have to do is get to the main assembly and read its custom attributes (which is what those lines from the AssemblyInfo file really). Here’s how:

Getting the main / entry assembly

The first thing is getting access to the correct – main (or entry) assembly. There are many ways to do that. At least one of those listed below should play nice with your your application architecture :

Assembly.GetExecutingAssembly() will get a reference to an assembly that’s executing that same code.

Assembly.GetCallingAssembly()will get a reference to an assembly of the method that called into this code.

The above methods don’t work well if the call is originating from the same dll. Exploring further…

Deployment.Current.EntryPointAssembly returns a name of the main assembly in pure string. You can use that to load the assembly with Assembly.Load(System.Windows.Deployment.Current.EntryPointAssembly). This will get you the main assembly, but it doesn’t feel right, so I finally settled with:

Application.Current.GetType().Assembly depends on using the Application static class, but since this is only used for a simple About page, that shouldn’t be  a significant problem.

Reading the attributes

I created the following helper method to read the attributes off an assembly:

private string GetAttribute<T>(Func<T, string> selector)
    where T: Attribute
{
    object[] attributes = assembly.GetCustomAttributes(typeof(T), true);
    if (attributes.Length == 0)
    {
        return "N/A";
    }
    T attribute = attributes[0] as T;
    return attribute == null ? "N/A" : selector(attribute);
}

GetCustomAttributes method overload above will return the only specified type of attribute you’re requesting, and the selector Func will read the value off of it. In the example of getting the Version attribute, here’s how you would use the function:

private string version;
public string Version
{
  get 
  {
    return version ?? 
      (version = GetAttribute<AssemblyFileVersionAttribute>(a => a.Version)); 
  }
}

For the application title, you would use the AssemblyTitle attribute:

private string title;
public string Title
{
  get 
  {
    return title ?? 
       (title = GetAttribute<AssemblyTitleAttribute>(a => a.Title)); 
  }
}

And so on…

And if you’d like, you can even create your own attributes, for example:

[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
[ComVisible(true)]
public class AssemblyContactAttribute : Attribute
{
    public string Email { get; private set; }
    public AssemblyContactAttribute(string email)
    {
        Email = email;
    }
}

Put that into the AssemblyInfo.cs file, as seen with other assembly attributes:

[assembly: AssemblyContact("myapp@tozon.info")]

and use the GetAttribute method similar to above examples.

You have just decorated your assembly with a new custom attribute that you can pull out at runtime.

By following those four points I was able to completely isolate my About page from main app(s) and adding the About page in my new apps is a matter of seconds. There is some convention involved of course (like the name of resources reference holding class), but I don’t see this as a problem. What do you think?



Windows Phone Pivot and loading content

Rewatching the Windows Phone Application Performance MIX10 talk by Jeff Wilcox, I took a note of one particular part where he clearly answers a question I’ve been asked a few times by now already. This question is based around the confusing statement that Pivot controls are supposed to be lazy loading their content pages, in contrast to Panoramas, which, at startup, would load all pages at once. The part that confuses developers the most is that when they start debugging their apps, they find out that Pivots load all their pages at startup too! How come? Aren’t Pivots loading pages only when needed?

Jeff explains this very clearly (fast forward to approx. minute 25) : “So the instant you go to a page, we pop up the Pivot, we’ll load  the content there. … …  Trouble is, we need to load more, because we want to provide a smooth experience when you pivot around. So we’re actually also loading, right after that first page comes up, we’ll kick off a load for both items on the left and the right.

See Jeff’s talk on the Channel 9 site.

What this means is that if your Pivot has only 2 or 3 pages, the startup performance won’t be that much different than when using a Panorama. If those 3 content pages are heavy on the load, use a lot of bindings etc., you can get into trouble. In some cases, loading a single content page on startup (and the rest when pivoted to) might actually result in a better experience than preloading all 3 pages.

Is there a way to override the default Pivot behavior and load only one content page on startup?

Of course there is.

The trick is to create a user control for each content page (which is a good idea anyway) and start it off with a Pivot control by specifying empty pages:

<controls:Pivot Title="My Pivot"
                LoadingPivotItem="OnLoadingPivotItem">
    <controls:PivotItem Header="Page 1" />
    <controls:PivotItem Header="Page 2" />
    <controls:PivotItem Header="Page 3" />
</controls:Pivot>

The LoadingPivotItem event will fire each time the Pivot would load a new content page. From MSDN documentation: “[LoadingPivotItem is an] Event for offering an opportunity to dynamically load or change the content of a pivot item before it is displayed.”

What you do during this event is check whether the content is loaded yet and if it isn’t, kick off the load. Something like:

private void OnLoadingPivotItem(object sender, PivotItemEventArgs e)
{
    if (e.Item.Content != null)
    {
        // Content loaded already
        return;
    }

    Pivot pivot = (Pivot)sender;

    if (e.Item == pivot.Items[0])
    {
        e.Item.Content = new Page1Control();
    }
    else if (e.Item == pivot.Items[1])
    {
        e.Item.Content = new Page2Control();
    }
    else if (e.Item == pivot.Items[2])
    {
        e.Item.Content = new Page3Control();
    }
}

One thing to have in mind though: make sure that any data you want to display on those content pages are loaded on the background thread (again – always a good idea) to allow the pages to load as quickly as possible.



NTK2011: Slides and sample code: MVVM

MVVM is a topic that can easily take hours of discussion. Unfortunately, I only had less then one to talk about (at least some of) its goals, parts and possible implementations. Below is my slide deck:

And the code: download

The code is structured in a way that helps you see the changes in the code while progressing through the samples. Just follow the numbers (e.g. MainPage1, MainPage2, and so on). It’s mainly Silverlight code, with the last example being example of an easy transition to Windows Phone.

The sample application is a conference app that lets you see available sessions. I removed the online data endpoint so the online samples won’t work, but you’ll get the feel using the offline data provider. Speaking of data providers, there are three (online/Ntk, using OData endpoint, Offline (loads Xml file from resources), and Json (same as Ntk, just for getting data in Json format – you know, for the phone Winking smile).

Once again, I have to stress out that code is for demo purposes only - while it’s minimized one end, it may be overly complicated on the other. Also, Silverlight Toolkit and JSON.NET libraries that were added through Nuget are not included in the zip.

Ah yes, the slides are in Slovenian language.



NTK 2011 Sample Code: What’s new in Silverlight 5

My “What’s new in Silverlight 5” session at NTK was mostly about showing sample code and samples, so no slide deck this time. The enclosed Visual Studio Silverlight project is configured for running Out-of-Browser, with GPU acceleration enabled, and requiring elevated permissions.

It’s basically a very basic video player application, used for playing videos from three preconfigured video sources: one’s your “My Videos” folder, one’s a custom local disk folder, and the last one is your favorite online TV show: the Silverlight TV (yes, it parses show’s feed to get the episodes list and info).

These sources play accordingly to the elevated permissions additions, made in Silverlight 5. The sample applications show off a lot of new Silverlight 5 features, some of them not so easily discoverable. Be sure to check out the source code to find them. This is a demo project and the code is somewhat unstructured. I’ll cover some of the new features in more details in the future, when Silverlight 5 fleshes out a bit more.

Download the sample project

Sample Silverlight 5