27Mar/124

Fixing the LongListSelector part 1: Recompile the source.

Today I came across an issue with the LongListSelector, part of the Silverlight for Windows Phone Toolkit. Solving the issue seemed pretty simple in the end, but first some background.

The LongListSelector is a control that can be used to create a list of groups. A good example of this is the contacts list in the people hub. In that list the contacts are organized based on the first letter of their name. Every group contains a header, in this case the first letter, and using this header you can very easily switch between groups. By using the LongListSelector from the toolkit, developers can create the same experiences in their apps.

The issue I encountered was the fact that I was getting ArgumentOutOfRange exceptions when an item was added to a group dynamically. This issue was supposed to be fixed in the November 2011 release, as stated in the release notes:

LongListSelector bug fixes around OutOfRange exceptions, wrong ordering of items, grouping issues, and scrolling events. ItemTuple is now refactored to be the public type LongListSelectorItem to provide users better access to the values in selection changed handlers.

Well this doesn't seem to be the case exactly. Most of those fixes were actually in changeset 71191 and 71199, which according to the codeplex site are included in the November release. This appears to be not so. When comparing some of the code in the installed Microsoft.Phone.Controls.Toolkit.dll to the source on codeplex it seems to be the case that the installed dll is compiled from a revision at least before 70993.

The solution is simple:

- Download the latest source from codeplex (this currently also includes some fixes to the PhoneTextBox, changeset 74775).

- Compile it.

- Use the resulting dll instead of the one installed by the toolkit.

Happy coding!

Did you like this? Share it:
24Mar/121

FontSize and pixel height in Silverlight for Windows Phone

Recently I came accross the issue where I wanted to limit the number of lines shown in my TextBlock on Windows Phone to for example 3. If the text was longer than 3 lines, the rest of the text should just not be shown. To do this I wanted to set the height of the TextBlock to a fixed height, to be exact 3 times the height of one line. This seems trivial, but to find the height of a line, you need to know something about the way Silverlight measures and calculates heights.

In Silverlight on the desktop and Silverlight for Windows Phone the measuring system is based on pixel units instead of Device Independent Pixel (DIP) units, as it is in WPF. Also the measuring system does not support unit measure string suffixes such as pt, cm or px. Silverlight measurements are always pixel units.

So if we specify the height of a Grid or a TextBlock to be 30 it actually is 30 pixel units. FontSize is no exception to this rule so when you specify 30 as the FontSize, you get a font that from the top of its ascenders to the bottom of its descenders measures approximately 36 pixels. Nevertheless the height of the corresonding TextBlock will be higher, because additional space is used to preserve space between successive lines. This concept is called leading.

In classical typography font sizes are expressed in units of points where a point is almost 1/72th of an inch. Digital typography assumes almost always a value of exactly 1/72th of an inch. This means that text with a font size of 72 points measures approximately 1 inch. Converting between pixels and points is difficult because it depends on the device you are using. Using a printer with 600 dpi (dots per inch) a font with size 72 will measure 600 pixels.

Windows assumes video displayes to have a dpi of 96. Using this assumption one can easily transform pixels into points and the other way around using the following two formulas:

points = 72/96 * pixels = 3/4 * pixels
pixels = 96/72 * points = 4/3 * points

Although Windows Phone screens have a much higher dpi than 96 these formulas also work for the phone. Suppose you want to set a 45 point font. Then you need to set the FontSize property to 60. On top of this Silverlight will add leading, which is approximately 33% of the size set as FontSize, which will result in the height of the TextBlock being 80 pixels.

It is possible to change this behavior by using the LineHeight and LineStackingStrategy properties of a TextBlock. You can read more about it here.

Did you like this? Share it:
13Aug/113

How to override theme resources in Windows Phone 7.5 (Mango)

Windows Phone 7 standard comes with some predefined themes and accent colors the user can choose of. You can read more about them here. This enables aaplications to automatically get adjusted to the users theme which makes the experience for user a lot better, because applications can adjust to the user's preferences. But sometimes this is not what you as a developer want. When you are for example building a facebook application you probably want the app to use the colors facebook uses, but you can of course have your own reason to not have your app always adjust to the current theme.

Windows Phone Themes

The different themes Windows Phone 7 comes with are included in the SDK and can be found in C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v7.0\Design on 64-bit windows installations and in C:\Program Files\Microsoft SDKs\Windows Phone\v7.0\Design on 32-bit installations. Each theme consists of a System.Windows.xaml file which defines the styles for the controls and a ThemeResources.xaml file which defines theme colors, brushes and text styles.

Overriding themes on Windows Phone 7.0

On Windows Phone 7.0 overriding the theme on the phone was quite easy and was well explained here and here. The technique comes down to defining a custom ResourceDictionary and add this ResourceDictionary to the Resources section in the app.xaml file.

<Application x:Class="ThemedApplication.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">

    <!--Application Resources-->
    <Application.Resources>
        <ResourceDictionary x:Key="styles">
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Themes/styles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

    <Application.ApplicationLifetimeObjects>
    <!--Required object that handles lifetime events for the application-->
    <shell:PhoneApplicationService
        Launching="Application_Launching" Closing="Application_Closing" 
        Activated="Application_Activated" Deactivated="Application_Deactivated"/>
    </Application.ApplicationLifetimeObjects>

</Application>

This resource dictionary can then be used to override theme resources, for example the PhoneBackgroundColor and PhoneBackgroundBrush can be defined to be always white in your application as shown below.

<ResourceDictionary
	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls">

	<!-- 100 percent White-->
	<Color x:Key="PhoneBackgroundColor">#FFFFFFFF</Color>

	<SolidColorBrush x:Key="PhoneBackgroundBrush" Color="{StaticResource PhoneBackgroundColor}"/>
</ResourceDictionary>

An example solution is attached at the bottom of this post.

Overriding themes in Windows Phone 7.5 (Mango)

When using the above overriding in a Windows Phone Mango application the technique does not work anymore. The reason behind this probably has to do with the switch between the silverlight 3 runtime and the silverlight 4 runtime which added support for implicit syles and a lot of other xaml changes. In a thread on the App Hub forums, about this technique not working anymore, Peter Torr, Program Manager in the Windows Phone 7 Application Platform team, explained that this was actually a bug in Silverlight on Windows Phone 7.0 and that this is "fixed" in Mango. He also gives two work-arounds you can use in Mango.

The first is the use of implicit styles which is a feature of silverlight 4 that now comes with mango. The problem with this approach is that you have to override the style for all controls to get them use the theme overrides. If you only want to change some colors this option costs a lot more work than before.

The second option is a lot better to implement if you just want to change some theme colors, although it is not as beautiful as simply including an extra resource dictionary. It works by changing the built-in styles instead of overriding them. This changing of styles can be done in the following way.

(App.Current.Resources["PhoneBackgroundBrush"] as SolidColorBrush).Color = Colors.White;

Another advantage of this technique over implicit styles is that this should also works on Windows Phone 7.0 although I did not test that. A disadvantage is that there is no design-time support when using this technique. One question that comes up is were to place these overrides. I found out by experience that the most useful place to put this overrides is after the InitializeComponent() method call in app.xaml.cs as shown below.

public partial class App : Application
{
        /// <summary>
        /// Provides easy access to the root frame of the Phone Application.
        /// </summary>
        /// <returns>The root frame of the Phone Application.</returns>
        public PhoneApplicationFrame RootFrame { get; private set; }

        /// <summary>
        /// Constructor for the Application object.
        /// </summary>
        public App()
        {
            // Global handler for uncaught exceptions. 
            UnhandledException += Application_UnhandledException;

            // Standard Silverlight initialization
            InitializeComponent();

            // Change default styles
            InitializeStyleChanges();

            // Phone-specific initialization
            InitializePhoneApplication();

            // Show graphics profiling information while debugging.
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // Display the current frame rate counters.
                Application.Current.Host.Settings.EnableFrameRateCounter = true;

                // Show the areas of the app that are being redrawn in each frame.
                //Application.Current.Host.Settings.EnableRedrawRegions = true;

                // Enable non-production analysis visualization mode, 
                // which shows areas of a page that are handed off to GPU with a colored overlay.
                //Application.Current.Host.Settings.EnableCacheVisualization = true;

                // Disable the application idle detection by setting the UserIdleDetectionMode property of the
                // application's PhoneApplicationService object to Disabled.
                // Caution:- Use this under debug mode only. Application that disables user idle detection will continue to run
                // and consume battery power when the user is not using the phone.
                PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
            }

        }

        // Code to execute when the application is launching (eg, from Start)
        // This code will not execute when the application is reactivated
        private void Application_Launching(object sender, LaunchingEventArgs e)
        {
        }

        // Code to execute when the application is activated (brought to foreground)
        // This code will not execute when the application is first launched
        private void Application_Activated(object sender, ActivatedEventArgs e)
        {
        }

        // Code to execute when the application is deactivated (sent to background)
        // This code will not execute when the application is closing
        private void Application_Deactivated(object sender, DeactivatedEventArgs e)
        {
        }

        // Code to execute when the application is closing (eg, user hit Back)
        // This code will not execute when the application is deactivated
        private void Application_Closing(object sender, ClosingEventArgs e)
        {
        }

        // Code to execute if a navigation fails
        private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // A navigation has failed; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        // Code to execute on Unhandled Exceptions
        private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
        {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                // An unhandled exception has occurred; break into the debugger
                System.Diagnostics.Debugger.Break();
            }
        }

        private void InitializeStyleChanges()
        {
            //87 percent Black - #DE000000
            (App.Current.Resources["PhoneForegroundBrush"] as SolidColorBrush).Color = Color.FromArgb(0xDE, 0x0, 0x0, 0x0);
            //100 percent White - #FFFFFFFF
            (App.Current.Resources["PhoneBackgroundBrush"] as SolidColorBrush).Color = Colors.White;
        }

        #region Phone application initialization

        // Avoid double-initialization
        private bool phoneApplicationInitialized = false;

        // Do not add any additional code to this method
        private void InitializePhoneApplication()
        {
            if (phoneApplicationInitialized)
                return;

            // Create the frame but don't set it as RootVisual yet; this allows the splash
            // screen to remain active until the application is ready to render.
            RootFrame = new PhoneApplicationFrame();
            RootFrame.Navigated += CompleteInitializePhoneApplication;

            // Handle navigation failures
            RootFrame.NavigationFailed += RootFrame_NavigationFailed;

            // Ensure we don't initialize again
            phoneApplicationInitialized = true;
        }

        // Do not add any additional code to this method
        private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
        {
            // Set the root visual to allow the application to render
            if (RootVisual != RootFrame)
                RootVisual = RootFrame;

            // Remove this handler since it is no longer needed
            RootFrame.Navigated -= CompleteInitializePhoneApplication;
        }

        #endregion
    }

An example using this technique is also attached below. If you have any questions on this don't hesitate to ask them in the comments.

WP7ThemedApplication

WP75ThemedApplication

Did you like this? Share it:
14Jul/111

Building the City Cloud part 1: Overall system architecture

The last couple of months I've been working on my bachelor project to finish my bachelor computer science. Together with Tom Verhoeff, Jos Kraaijeveld, Jochem Toolenaar and Oana Nitu, I participated in the Imagine Cup 2011. We formed team O!ife and our project was called the City Cloud. The City Cloud is a cloud computing platform that allows different kinds of data generated by the city, its inhabitants, companies and its government to be easily accessed by developers to create new innovative technologies and solutions. You can find more about the City Cloud on the O!ife blog.

This post is one in a series on how we built the City Cloud and everything around it. The focus of these posts will be on the technical aspects of the City Cloud. It will also cover some problems we encountered during development and the solutions we used to tackle them. At this moment I have no idea how many parts will follow. We've came across lots of different problems and used lots of technologies, so I will write another part whenever I have the time and when I think the topic is interesting enough for other developers. The first part will cover the overall architecture of the system to establish a background for other posts.

Goal

When we started the City Cloud project we thought of it as a developer platform for a city. The main goal should be to offer the correct tools for developers to build next generation ubiquitous applications: it should be easy to expose new datasets through the system and the development of applications using these datasets should not require large investments in both terms of infrastructure and programming skills.

In the design phase we divided the system up into three parts: the cloud framework, the mobile platform and the website/webapplication. The framework was the heart of the system and was designed to run in the Azure cloud. Its responsibility was to present the data that is part of the system in an easy and consistent way and offering an all-in-one solution for data and app storage. The mobile platform and the website/webapplication functioned as two different portals to the data and the apps. The website should give general information on cities and should show the datasets and applications available. It should also provide developers with documentation and best practices on how to make use of the platform's capabilities in the best possible way. The mobile framework should be the main portal to the end user in a city. It should give an user specific information on data and apps based on his current location. With more and more smartphones sold every day, smartphones offered a great opportunity to be the number one entry point to the City Cloud.

Framework

The framework should expose data in an easy way. To achieve this we decided to go with an OData webservice running in an Azure webrole. Besides being a Microsoft technology which counts for the Imagine Cup, OData offers an excellent way to expose datasets and besides that offers great possibilities to perform transformations and filtering on the returned data. Another advantage is the great tools available to develop OData webservices and to consume them on almost all major platforms. To get data into the City Cloud framework we invented "connectors". To expose a new dataset through the framework all a developer would need to do is build a connector that allows the City Cloud to retrieve data from their data source. This connector should implement some interface, provide the system with some description of the data structures and it should all magically come to life.

Mobile platform

To reach as much as possible users we wanted the mobile platform to run not only on Windows Phone, but also on Android and iOS. But we didn't want developers to write the same application three times for three different platforms. To accomplish this we decided to go with html5 and javascript as the tools to build the applications for our mobile platform. On every major smartphone platform it is possible to embed some kind of web browser control into a native application and load webpages in it and with the Mango update for Windows Phone coming this fall, html5 is also broadly supported on all mobile phones. We call these html5 applications "building blocks". These building blocks could be hosted in the City Cloud framework and could use datajs to interact with the OData webservice via javascript.

Website and webapplication

To give developers and users an overview of the data and applications already in the system we built the website including a Silverlight webapplication. The webapplication was meant to be used as an explorer for the webservice. In this way everybody could take a quick look into the system to browse data. It also offered the possibility to plot these datasets on a map.

Extensibility

Developers could use the website to submit new applications and new connectors to the system. Because of the extensibility model we felt the need to building a validation step to verify the working of the newly submitted parts in the framework. To validate new submissions we made use of a core feature of the azure platform: a worker role. In Windows Azure a worker role is meant to be used for background processing or other long running tasks. In the cloud framework we used a worker role to validate a submission and to make the required changes to the framework to add a new connector or building block.
At the end of the design phase the overall system architecture looked a lot like a high level Model-View-Controller architecture. The website and the mobile platform functioned as the views, while the framework holds the current state of the system and functioned as the model. The worker role was used to change the state of the framework and can thus be seen as the controller. The following image shows the high level architecture in a graphical way:

I hope this gives a good overview of the system we built the last couple of months. Unfortunately no code yet, but I will save that for the next part.

Did you like this? Share it: