Daniel Vaughan

free range code

Generating Localized Resources in Mono for Android Using T4

clock April 14, 2013 08:17 by author Daniel Vaughan

Introduction

Recently I have been using the Xamarin products: Mono for iOS and Mono for Android, to port some of our Windows Phone apps to iOS and Android. I like the Xamarin products a lot. Being able to contain most of my development activities to the familiar environment of Visual Studio has made getting up to speed easier.

One key facet of the Xamarin products, in particular Mono for Android, is that they do not attempt to overly abstract the APIs of the underlying platform. When you are working with Mono for Android, the class hierarchy, in the most part, mirrors that of the Java Android SDK. This means that you don’t miss out on learning how ‘native’ development is done, and that you aren’t introducing an undue dependency on a third party API.

There isn’t a built-in unified UI framework for Xamarin’s mono products. You still have to define your views separately for each platform. Obviously this adds to development time, yet it makes sense. Each platform has a different look and feel, and users prefer apps that conform to the UI conventions of their particular mobile platform. There are open source projects out there that attempt to bridge the gap. If though, you wish to leverage the UI visual development tools provided by Xcode and Visual Studio, there is no getting away from providing a separate UI implementation for each platform. If you are new to iOS development like I am, then using Xcode’s Interface Builder also allows you to explore and improve your understanding of the UI framework.

Aside from the absence of a unified UI framework, there is also a major difference in the localization model in Mono for Android. Mono for Android uses the same localization model as that of apps built in Java using the Android SDK. This creates an incompatibility with Windows Phone and Mono for iOS projects, which both normally use Resx files for localization.

This article looks at creating a T4 template to generate a Mono for Android localization files from Resx files. You see how to reuse the template with the import directive. You see how to generate a designer class with statically typed properties using T4. Finally the article demonstrates how to dynamically change the UI language at run-time.

Localization Model Differences Between .NET and Mono for Android

Although Mono for Android's localizability model is markedly different to the Resx model, they do have similarities. Android’s string localization model uses XML files, containing key value pairs that declare localized strings in your app. Unlike .NET, however, these files are placed in a Resources directory within your Mono for Android project and compilation to satellite assemblies does not occur.

In Android, you add support for additional languages by creating additional XML files; placing them in folders within the Resources directory that are suffixed with language and region codes. Android chooses the appropriate set of resources depending on the locale that the app is running under. This is much like the .NET hub and spoke localization model, where a default Resx file is complimented by other localized Resx files. If a string cannot be located in a specific language, fall back occurs to the default resource file.

In .NET, Resx files are accompanied by a generated designer class that allows you to reference localized strings using statically typed properties, which gives you compile time assurance that the resource names have been correctly specified in your code. Although Mono for Android also generates a designer class, it surfaces the resources as an integer identifier, which introduces an extra step to retrieving a localized resource. If you link files into your Mono for Android project that make use of the .NET designer class then your project will not compile. The designer class in the .NET project makes use of a ResourceManager object and retrieves localized resources in a manner that does not work in Android. Thus, in addition to needing a way to convert each Resx file to an Android localized string file, you need a way to generate a Mono for Android-friendly designer class.

Converting a Resx File to a Mono for Android Localized XML File

Resx files are XML files comprised of, among other things, data elements, which specify the name of the resource and its localized value (see Listing 1).

Listing 1. Resx File (Excerpt)

<?xml version="1.0" encoding="utf-8"?>
<root>
  ...
  <data name="Greeting" xml:space="preserve">
    <value>Hello</value>
  </data>
</root>

The downloadable sample code includes a T4 template named ResxToAndroidXml.txt (see Listing 2). The file contains a single method named Process that accepts a path to a Resx file and converts the Resx to an Android compatible localized resource file. It does this by loading the Resx file into an XDocument object. Each data node within the Resx is written as a string element in the resulting Android resource file.

Listing 2. ResxToAndroidXml.txt

<#@ output extension=".xml" #>
<#@ template language="C#" hostSpecific="true" #>
<#@ assembly name="System.Core" #>
...
<#@ import namespace="System.Globalization" #><#+

public void Process(string resxRelativePath)
{
    WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
    WriteLine("<resources>");

    XDocument document;
    try
    {
        document = XDocument.Load(resxRelativePath);
    }
    catch (FileNotFoundException)
    {
        WriteLine("<!-- File not found: " + resxRelativePath + " -->");
        WriteLine("</resources>");
        return;
    }

    IEnumerable<XElement> dataElements = document.XPathSelectElements("//root/data");

    foreach (XElement element in dataElements)
    {
        string elementName = element.Attribute("name").Value;
        string elementValue;

        XElement valueElement = element.Element("value");

        if (valueElement != null)
        {
            elementValue = valueElement.Value;
        }
        else
        {
            continue;
        }

        string cleanedValue = elementValue.Replace("'", "\\'");

        WriteLine(string.Format("    <string name=\"{0}\">{1}</string>", elementName, cleanedValue));
    }

    WriteLine("</resources>");    
}
#>

Android requires that localized files be placed in directories named according to the culture and region codes (see Figure 1). The default string resources are placed in a Values directory. Localized resources are placed in directories suffixed with the culture and optionally a region code.

Figure 1. The Sample Android Project Structure

To create a T4 template in your Mono for Android project, add a new text file to the project using the Add New Item dialog, and then rename the file, giving it a .tt file extension.

A String.tt template, which references the ResxToAndroidXml.txt include, is placed in each Values directory. Each specifies a different Resx file in the .NET project, as demonstrated in Listing 3.

Listing 3. Strings.tt

<#@ include file="..\..\..\..\ResxToAndroidXml.txt" #>
<#@ output extension=".xml" #>
<#@ template language="C#" hostSpecific="true" #>
<#
	Process(Path.GetDirectoryName(Host.TemplateFile) 
             + "../../../../AndroidResxT4/Resources/AppResources.resx");
#>

Resulting String.xml files must have their Build Action set to AndroidResource (see Listing 4). You can see that the name attribute of the data element in the Resx file maps to the name attribute of the string element in the Android resource, and that the value element in the Resx file maps to the content of the string element in the Android resource.

Listing 4. Strings.xml

<?xml version="1.0" encoding="utf-8" ?>
<resources>
    <string name="Greeting">Hello</string>
</resources>

Generating Statically Typed Properties for Resource Values

The generated Mono for Android localized string files can be consumed in Mono for Android layout files or in code. Recall, however, that the generated Resx designer class in the .NET project cannot be reused in your Android project. What you need is an independent designer class just for the Mono for Android project that contains the same properties as the .NET Resx designer class. For this we turn to T4 once again.

The ResxToAndroidAccessorClass.txt file in the downloadable sample is a T4 template with a single method named Process. Process accepts the path to your Resx file and the namespace you wish the resulting designer class to reside in (see Listing 5). The method attempts to load the Resx file into an XDocument object and then generates a property element for each data element in the Resx file. The class is placed into the specified namespace. This allows you to align the code with that of your .NET project.

Listing 5. ResxToAndroidAccessorClass.txt Process Method

<#@ output extension=".cs" #>
<#@ template language="C#" hostSpecific="true" #>
<#@ assembly name="System.Core" #>
...
<#@ import namespace="System.Globalization" #><#+

public void Process(string resxRelativePath, string namespaceName)
{
    WriteLine("using Android.App;");
    WriteLine("namespace " + namespaceName);
    WriteLine("{");
    WriteLine("    public class AppResources {");
    XDocument document;
    try
    {
        document = XDocument.Load(resxRelativePath);
    }
    catch (FileNotFoundException)
    {
        WriteLine("<!-- File not found: " + resxRelativePath + " -->");
        WriteLine("}}");
        return;
    }

    IEnumerable<XElement> dataElements = document.XPathSelectElements("//root/data");

    foreach (XElement element in dataElements)
    {
        string elementName = element.Attribute("name").Value;
        string elementValue;

        XElement valueElement = element.Element("value");

        if (valueElement != null)
        {
            elementValue = valueElement.Value;
        }
        else
        {
            continue;
        }

        string cleanedValue = elementValue.Replace("'", "\\'");

        WriteLine(string.Format("public static string {0} {{ get {{ return Application.Context.GetString(Resource.String.{0}); }}}}", elementName));
    }

    WriteLine("}}");
}
#>

To leverage the ResxToAndroidAccessorClass.txt file, create a T4 file named AppResources.tt in your Mono for Android project. Use the include directive to import the template and call the Process method with the path of the Resx file and the desired namespace (see Listing 6).

Listing 6. AppResources.tt

 <#@ include file="..\..\ResxToAndroidAccessorClass.txt" #>
<#@ output extension=".cs" #>
<#@ template language="C#" hostSpecific="true" #>
<#
	Process(Path.GetDirectoryName(Host.TemplateFile) 
                  + "../../AndroidResxT4/Resources/AppResources.resx", "AndroidResxT4");
#>
 

The template produces a class with properties for all of the localized string in your default resource file (see Listing 7)

Listing 7. AppResources.cs in Mono for Android Project

using Android.App;
namespace AndroidResxT4
{
	public class AppResources {
		public static string Greeting { get { return Application.Context.GetString(Resource.String.Greeting); }}
}}

The AppResources class in your Mono for Android project should mirror your designer class in your .NET project, allowing you to seamlessly link to classes in your .NET project without breaking compilation.

Sample Project Overview

In addition to converting Resx to Android resources and generating a resource designer class, the downloadable sample code demonstrates how to change the UI language of your Mono for Android app at runtime.

The MainActivity class contains a SetLocale method that creates a new Locale object and updated the app’s configuration (see Listing 8). The AttachView and DetachView methods subscribe and unsubscribe to the button’s Click event.

Listing 8. SetLocale Method

void SetLocale(string languageCode)
{
    Resources resources = Resources;
    Configuration configuration = resources.Configuration;
    configuration.Locale = new Java.Util.Locale(languageCode);
    DisplayMetrics displayMetrics = resources.DisplayMetrics;
    resources.UpdateConfiguration(configuration, displayMetrics);

    DetachView();

    SetContentView(Resource.Layout.Main);

    AttachView();
}

Updating the configuration with a French Locale, specified using the ‘fr’ language code, causes the text of a TextView to change from Hello to Bonjour, as shown in Figure 2.

Figure 2. Tapping the Change Locale Button Switches the Language

The AppResources class can be used as it would in a .NET app. Notice that tapping the button writes the localized Greeting message to the console (see Listing 9).

Listing 9. Button.Click Handler

void HandleButtonClick(object sender, EventArgs e)
{
    SetLocale(!localeToggled ? "fr" : "en");
    localeToggled = !localeToggled;

    Console.WriteLine(AppResources.Greeting);
}

Summary

This article looked at creating a T4 template to generate a Mono for Android localization file. You saw how to reuse T4 templates using the import directive. You saw how to generate a designer class with statically typed properties using T4. Finally the article demonstrated how to dynamically change the UI language of an Android app at run-time.

If you apply the principles of SoC and avoid mixing platform specific API calls in your app logic, you can maximize code reuse across platforms. I have almost completed porting the entirety of the Calcium SDK base library to Mono for Android and Mono for iOS. Calcium includes numerous features that make building multifaceted maintainable apps easier, including an IoC and DI system and a user preference API. Anyway, more on that later.

Sample: AndroidResxT4_01.zip (52.71 kb)



Knockout Style Observables in XAML

clock July 15, 2012 11:22 by author Daniel Vaughan

This week there was a short discussion on the WPF Disciples about Knockout observables and the implications of field level and owner level data bindings. The discussion can be found in the guts of this post.

I wanted to explore the topic further, and I decided to take a stab at implementing something analogous to Knockout Observables and Computed Observables in WPF.

In this article we look at implementing field level change notification in WPF, and how a Lambda Expression can be used to specify a composite property that raises change notifications automatically whenever an associated property changes.

To get started, let’s first take a look at a class that illustrates how composite binding are ordinarily done in a viewmodel designed for XAML (see Listing 1). It’s a simple viewmodel that contains three properties. Two properties have backing fields, while the third (FullName) is a composite property; combining the FirstName and LastName properties. When either of the non-composite properties change, change notification has to occur for the composite as well as non-composite properties.

The downside of this approach is that as the complexity of the viewmodel increases and dependencies creep in, you end up having to raise PropertyChanged events for multiple dependent properties. While this example may seem dead simple (it is), over time potential faults may creep in because of this kind of interdependence.

Listing 1. MainWindowViewModelTraditional Class

class MainWindowViewModelTraditional : INotifyPropertyChanged
{
    string firstName;
        
    public string FirstName
    {
        get
        {
            return firstName;
        }
        set
        {
            if (firstName != value)
            {
                firstName = value;
                OnPropertyChanged("FirstName");
                OnPropertyChanged("FullName");
            }
        }
    }

    string lastName;

    public string LastName
    {
        get
        {
            return lastName;
        }
        set
        {
            if (lastName != value)
            {
                lastName = value;
                OnPropertyChanged("LastName");
                OnPropertyChanged("FullName");
            }
        }
    }

    public string FullName
    {
        get
        {
            return firstName + " " + lastName;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Taking the Knockout JS Approach

I’ve been using Knockout quite a bit lately and I like the flexibility and versatility that the binding expression interpreter offers. Knockout allows you to combine observable values in a way that allows you to forego the kind of artificial dependence seen earlier. For example, on a web page you can produce the same string as the FullName property seen in the last example using something like the following:

<span data-bind="text: firstName() + ' ' + lastName()"></span>

You can also achieve the same result using computed values in your viewmodel if you so desire.

In this article I’ve set out to see whether I could come up with something that emulates Knockout's field level notifications in observables and computed observables. I’m quite happy with the result and I believe it has potential. Stay tuned, because at the end of this article you will see how to create a computed property in C# like the following, which raises change notifications automatically:

readonly ComputedValue<string> fullName;

public ComputedValue<string> FullName
{
    get
    {
        return fullName;
    }
}

public MainWindowViewModel()
{
    fullName = new ComputedValue<string>(() => FirstName.Value + " " + ToUpper(LastName.Value));
}

Bridging the HTML-XAML Ravine

In WPF, when using the INotifyPropertyChanged approach to data binding, change notification occurs at the owner object level. The owner is the source property in a data binding, which is ordinarily the DataContext of your control. If you’re using the MVVM pattern this is likely your viewmodel or a nested property. It is the owner object of the property that has the responsibility of raising a PropertyChanged event whenever the property changes.

Conversely, field level notification is where the source of the notification is the field itself (or in XAML, a property). The main advantage of field level notification is that your viewmodel does not need to contain any plumbing code for change notification. Field level notification isn’t achievable in XAML without defining an event for each property in your viewmodel. (Thanks to Bill Kemph for reminding me of field level notifications using dedicated events). This approach is usually avoided because it adds an undue amount of plumbing code to your viewmodel. A wrapper layer is presented in this article, which takes care of raising property changed events for you.

Two classes exist in the downloadable code that emulate the behaviour of Knockout’s observable and computed observable types: ObservableValue and ComputedValue. Both implement INotifyPropertyChanged and automatically raise the PropertyChanged event when an associated value has changed.

The ObservableValue implementation is rudimentary. Things get more interesting when we look at the ComputedValue implementation that allows you to specify a LINQ expression, which is parsed by the ComputedValue object to locate objects that implement INotifyPropertyChanged. When any such object changes, the computed value is recalculated. This allows you to create arbitrary composite properties in your viewmodel that respond to change notifications of any other associated object.

Understanding the ObservableValue Class

An ObservableValue property is defined much like a property using the traditional approach to INPC. The difference is that an ObservableValue instance wraps the value, as shown in the following excerpt:

class MainWindowViewModel
{
    readonly ObservableValue<string> firstName = new ObservableValue<string>("Alan");

    public ObservableValue<string> FirstName
    {
        get
        {
            return firstName;
        }
    }
…
}

To set the value, the ObservableValue.Value property is used. When the setter is used the PropertyChanged event is raised (see Listing 2).

Listing 2. ObservableValue Class

public class ObservableValue<T> : INotifyPropertyChanged
{
    T valueField;

    public T Value
    {
        get
        {
            return valueField;
        }
        set
        {
            if (!EqualityComparer<T>.Default.Equals(valueField, value))
            {
                valueField = value;
                OnPropertyChanged("Value");
            }
        }
    }

    public ObservableValue(T value = default(T))
    {
        Value = value;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Creating Composite Properties with the ComputedValue Class

Unlike ObservableValue, ComputedValue accepts a Lambda Expression that, when compiled, returns a value for the property. Listing 3 shows how the ComputedValue's constructor uses a specified Lamdba Expression.

Listing 3. ComputedValue Class (Excerpt)

public class ComputedValue<T> : INotifyPropertyChanged, IDisposable
{
…
    readonly Func<T> valueFunc;

    public T Value
    {
        get
        {
            T result = valueFunc();
            return result;
        }
    }

    public ComputedValue(Expression<Func<T>> expression)
    {
        if (expression == null)
        {
            throw new ArgumentNullException("expression");
        }

        Expression body = expression.Body;

        ProcessDependents(body);

        valueFunc = expression.Compile();
    }
…
}

When an instance of ComputedValue is created, the specified expression is parsed recursively. Nested MemberExpressions that refer to objects implementing INotifyPropertyChanged are identified (see Listing 4).

Listing 4. ProcessDependents (Excerpt)

void ProcessDependents(Expression expression)
{
    switch (expression.NodeType)
    {
        case ExpressionType.MemberAccess:
            ProcessMemberAccessExpression((MemberExpression)expression);
            break;
        case ExpressionType.Call:
            ProcessMethodCallExpression((MethodCallExpression)expression);
            break;
...
        default:
            return;
    }
}

When a member expression is discovered, its owner is resolved using the ComputedValue.GetValue method. The class subscribes to the PropertyChanged event of the owner object. A PropertyChangedEventHandler is created and placed in a collection along with a WeakReference to the owner object (see Listing 5). When a change notification is received, the ComputedValue object raises its own PropertyChanged event.

Listing 5. ProcessMemberAccessExpression Method

void ProcessMemberAccessExpression(MemberExpression expression)
{
    Expression ownerExpression = expression.Expression;
    Type ownerExpressionType = ownerExpression.Type;
                                            
    if (typeof(INotifyPropertyChanged).IsAssignableFrom(ownerExpressionType))
    {
        try
        {
            string memberName = expression.Member.Name;
            PropertyChangedEventHandler handler = delegate(object sender, PropertyChangedEventArgs args)
                {
                    if (args.PropertyName == memberName)
                    {
                        OnValueChanged();
                    }
                };

            var owner = (INotifyPropertyChanged)GetValue(ownerExpression);
            owner.PropertyChanged += handler;

            handlers[handler] = new WeakReference(owner);
        }
        catch (Exception ex)
        {
            Console.WriteLine("ComputedValue failed to resolve INotifyPropertyChanged value for property {0} {1}", 
                                expression.Member, ex);
        }
    }
}

Retrieving the property value from the Lambda expression is done via expression compilation (see Listing 6). However, the expression is not able to be compiled directly as it is just a fragment. A Lambda expression is constructed by converting the specified expression into a UnaryExpression. When compiled, the resulting func is called and the result returned. In most cases the result is your viewmodel. Though, it does not have to be.

Listing 6. GetValue Method

object GetValue(Expression expression)
{
    UnaryExpression unaryExpression = Expression.Convert(expression, typeof(object));
    Expression<Func<object>> getterLambda = Expression.Lambda<Func<object>>(unaryExpression);
    Func<object> getter = getterLambda.Compile();

    return getter();
}

In .NET the target of an event may be ineligible for garbage collection while the event source remains alive. Therefore if we do not unsubscribe from owner objects’ PropertyChanged events, a memory leak may ensue. The ComputedValue class implements IDisposable and when disposed the ComputedValue instance unsubscribes from all change events.

The ComputedValue IDisposable implementation loops over the items in the handlers dictionary (see Listing 7). If KeyValuePair.Value property holds a WeakReference to the owner of the property, where the owner has not been disposed, the PropertyChanged event is unsubscribed using the handler stored as the KeyValuePair.Key property.

Listing 7. ComputedValue IDisposable Implementation

bool disposed;

protected virtual void Dispose(bool disposing)
{
    if (!disposed)
    {
        if (disposing)
        {
            foreach (KeyValuePair<PropertyChangedEventHandler, WeakReference> pair in handlers)
            {
                INotifyPropertyChanged target = pair.Value.Target as INotifyPropertyChanged;
                if (target != null)
                {
                    target.PropertyChanged -= pair.Key;
                }
            }

            handlers.Clear();
        }

        disposed = true;
    }
}

public void Dispose()
{
    Dispose(true);
}

The downloadable code contains a simple single window application that displays two TextBox controls. Each TextBox is bound to a viewmodel property of type ObservableValue. There is a TextBlock that is bound to a ComputedValue property, which combines the result of the two ObservableValue properties (see Figure 1). When the text in either of the TextBoxes is changed, the TextBlock containing the full name is updated.

Note how the LastName property is converted to upper case. This is performed despite the fact that the call is embedded within the Lambda expression of the ComputedValue.

Figure 1.Sample App.

Just to prove no funny business is taking place in the Window XAML, Listing 8 shows how the text properties are bound to the Value property of the ObservableValue properties and the ComputedValue property.

Listing 8. MainWindows.xaml (Excerpt)

<StackPanel Orientation="Horizontal" Margin="40">
    <StackPanel>
        <Label>First Name</Label>
        <TextBox Text="{Binding Path=FirstName.Value, UpdateSourceTrigger=PropertyChanged}" />
        <Label>Last Name</Label>
        <TextBox Text="{Binding Path=LastName.Value, UpdateSourceTrigger=PropertyChanged}" />
    </StackPanel>
    <StackPanel Margin="20,0">
        <Label>Full Name</Label>
        <TextBlock Text="{Binding Path=FullName.Value}" 
                    Style="{StaticResource FullNameStyle}" />
                
        <TextBlock>fullName = new ComputedValue&lt;string&gt;(<LineBreak />
            () => FirstName.Value + " " + ToUpper(LastName.Value));</TextBlock>
    </StackPanel>
</StackPanel>

The MainWindowViewModel code is shown in its entirety in Listing 9. The FirstName and LastName properties are combined in the ComputedValue, along with an arbitrary call to a ToUpper method.

Listing 9. MainWindowViewModel Class

class MainWindowViewModel
{
    readonly ObservableValue<string> firstName = new ObservableValue<string>("Alan");

    public ObservableValue<string> FirstName
    {
        get
        {
            return firstName;
        }
    }

    readonly ObservableValue<string> lastName = new ObservableValue<string>("Turing");

    public ObservableValue<string> LastName
    {
        get
        {
            return lastName;
        }
    }

    readonly ComputedValue<string> fullName;

    public ComputedValue<string> FullName
    {
        get
        {
            return fullName;
        }
    }

    public MainWindowViewModel()
    {
        fullName = new ComputedValue<string>(() => FirstName.Value + " " + ToUpper(LastName.Value));
    }

    string ToUpper(string s)
    {
        return s.ToUpper();
    }
}

Knockout JS has some elegant features that leverage the versatility of JavaScript and help to bridge the gap between XAML and HTML. In this article we looked at implementing field level change notification in WPF, and how a Lambda Expression can be used to specify a composite property that raises change notifications automatically whenever an associated property changes.

Vaughan.ObservablePrototype_2012_07_15.rar (250.68 kb)

Follow me on twitter



Using T4 to Generate Windows Phone WMAppManifest Files

clock April 6, 2012 01:44 by author Daniel Vaughan

Recently, Eric Schoenholzer began an interesting discussion on the Windows Phone Experts group on linkedin centred around techniques for effectively monetizing your apps on the Windows Phone marketplace. In particular, he raised the interesting question of whether it is better to publish a single app with a trial, or whether it is more effective to go for two apps: a free version with ads and a paid version without ads. These days I favour the later in most cases (I explain why in linkedin discussion). But the downside is that because of the reliance on the WMAppManifest file in your phone app, it often means you have to maintain two versions of your app. Rather than do that, my approach has been to rely on a T4 template to generate the WMAppManifest file, which takes care of changing various fields such as the title of the app depending on the value of a pre-processor directive. This allows you to maintain a single version of your app, and a single version of your WMAppManifest file. It’s an approach that I have used in several published apps, and it has made maintaining them that little bit easier.

To replace the static WMAppManifest file with a dynamic T4 generated file, perform the following steps:

  1. Add a new text file named WMAppManifest.txt to your project.
  2. Place the text file in the Properties directory of your project by dragging it with the Visual Studio Solution Explorer.
  3. Copy the contents of the existing WMAppManifest.xml file to the newly created WMAppManifest.txt file. When you paste the text, you may find it is incorrectly formatted as HTML. This is Visual Studio trying to be helpful, but in this case we want the text pasted as is. Press Ctrl-Z once, and the auto-formatting will be removed.
  4. Add the following T4 directives to the top of the WMAppManifest.txt file:
    <#@ template debug="false" hostspecific="true" language="C#" #>
    <#@ output extension=".xml" #>
    Notice that the template directive specifies that the template is host specific. This gives the template access to the Visual Studio DTE, which is discussed later in this article.
  5. Delete the existing WMAppManifest.xml file.
  6. Rename WMAppManifest.txt to WMAppManifest.tt. This should produce a WMAppManifest.xml file, which is nested beneath the T4 template (as shown in Figure 1).

Solution Explorer with T4 template

Figure 1: Solution Explorer with T4 template

Using a T4 template to generate the WMAppManifest file is, in itself, not difficult. The fun part is determining your project configuration from the T4 template. This can be done by reading a property value, which is set according to a preprocessor directive, from the template. The system I use is convention based. It relies on a class called DeploymentConfiguration, which is expected to contain a Boolean constant named PaidConfiguration (see Listing 1). A preprocessor directive determines the value of the PaidConfiguration constant. The DeploymentConfiguration class contains several other related properties that can be used to determine the visibility and behaviour of visual elements based on whether the app has been purchased or not.

Listing 1: DeploymentConfiguration Class

//#define PAID

class DeploymentConfiguration
{
    /// <summary>
    /// The app identifier for the non-free version of the app. 
    /// This is used to provide a link to buy the paid app from the free app.
    /// </summary>
    public static string PaidAppId
    {
        get
        {
            return "11111111-1111-1111-1111-11111111";
        }
    }

    public static string AdAppId
    {
        get
        {
#if DEBUG
            return "test_client";
#else
            return "11111111-1111-1111-1111-11111111";
#endif
        }
    }

    public static string AdUnitId
    {
        get
        {
            return "11111";
        }
    }

    /* This should be false when publishing a paid version; true otherwise. */
    public static bool ShowAds
    {
        get
        {
            return !PaidConfiguration;
        }
    }

    public static bool Paid
    {
        get
        {
            return PaidConfiguration;
        }
    }

    public const bool PaidConfiguration =
#if PAID
 true;
#else
 false;
#endif
}

As you see in a moment, the WMAppManifest.tt relies on a include file named ProjectVariables.ttinclude (see Listing 2). ProjectVariables.ttinclude relies on the DTE, which is the top level Visual Studio automation object. The DTE allows you to traverse the structure of your solution. In this case, it is used to retrieve the value of the PaidConfiguration constant in the DeploymentConfiguration.cs file.

Listing 2: ProjectVariables.ttinclude

<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Globalization" #>
<# 
/* Retrieve the DTE. */
IServiceProvider hostServiceProvider = (IServiceProvider)Host;
EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));
/* Retrieve the project in which this template resides. */
EnvDTE.ProjectItem containingProjectItem = dte.Solution.FindProjectItem(Host.TemplateFile);
Project project = containingProjectItem.ContainingProject;
var projectName = project.FullName;
ProjectItem deploymentConfiguration = GetProjectItem(project, "DeploymentConfiguration.cs");

if (deploymentConfiguration == null)
{
    throw new Exception("Unable to resolve DeploymentConfiguration.cs file");
}

var codeModel = deploymentConfiguration.FileCodeModel;
bool paid = false;

foreach (CodeElement codeElement in codeModel.CodeElements)
{
    if (codeElement.Name == "DeploymentConfiguration")
    {
        CodeClass codeClass = (CodeClass)codeElement;
        foreach (CodeElement memberElement in codeClass.Members)
        {
            if (memberElement.Name == "PaidConfiguration")
            {
                CodeVariable variable = (CodeVariable)memberElement;
                paid = bool.Parse(variable.InitExpression.ToString());
            }
        }
    }
} 
#>
<#+ EnvDTE.ProjectItem GetProjectItem(Project project, string fileName)
{
    foreach (ProjectItem projectItem in project.ProjectItems)
    {
        if (projectItem.Name.EndsWith(fileName))
        {
            return projectItem;
        }
        var item = GetProjectItem(projectItem, fileName);
        if (item != null)
        {
            return item;
        }
    }
    return null;
}

EnvDTE.ProjectItem GetProjectItem(EnvDTE.ProjectItem projectItem, string fileName)
{
    if (projectItem.ProjectItems != null 
        && projectItem.ProjectItems.Count > 0)
    {
        foreach (ProjectItem item in projectItem.ProjectItems)
        {
            if (item.Name.EndsWith(fileName))
            {
                return item;
            }
        }
    }
    return null;
} 
#>

When the ProjectVariables.ttinclude is defined as an include in the WMAppManifest.tt file, the value of the paid variable can be used to determine the title of the app and any other configurable aspects of the app (see Listing 3).

A title variable is assigned according to the value of the paid variable (defined in the ProjectVariables.ttinclude). The title variable is then used within the App element.

You’ll notice that the include file directive immediately precedes the string title variable definition, and that there is no space between them. This isn’t merely a case of sloppy formatting but rather the positioning of line breaks within the T4 template is important. Adding a line break produces an invalid WMAppManifest, because the xml definition must be placed on the first line of the file.

Listing 3:WMAppManifest.tt T4 Template

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".xml" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System.Globalization" #>
<#@ include file="ProjectVariables.ttinclude" #><#
string title = paid ? "My App Pro" : "My App with Ads";
#>
<?xml version="1.0" encoding="utf-8"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2009/deployment" AppPlatformVersion="7.1">
  <App xmlns="" ProductID="{11111111-1111-1111-1111-111111111111}" Title="<#= title #>" RuntimeType="Silverlight" 
       Version="1.0.0.0" Genre="apps.normal"  Author="Example Author" Description="Sample description" Publisher="Example Publisher">

    <IconPath IsRelative="true" IsResource="false">ApplicationIcon.png</IconPath>
    <Capabilities>
      <Capability Name="ID_CAP_GAMERSERVICES"/>
      <Capability Name="ID_CAP_IDENTITY_DEVICE"/>
      <Capability Name="ID_CAP_IDENTITY_USER"/>
      <Capability Name="ID_CAP_LOCATION"/>
      <Capability Name="ID_CAP_MEDIALIB"/>
      <Capability Name="ID_CAP_MICROPHONE"/>
      <Capability Name="ID_CAP_NETWORKING"/>
      <Capability Name="ID_CAP_PHONEDIALER"/>
      <Capability Name="ID_CAP_PUSH_NOTIFICATION"/>
      <Capability Name="ID_CAP_SENSORS"/>
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
      <Capability Name="ID_CAP_ISV_CAMERA"/>
      <Capability Name="ID_CAP_CONTACTS"/>
      <Capability Name="ID_CAP_APPOINTMENTS"/>
    </Capabilities>
    <Tasks>
      <DefaultTask  Name ="_default" NavigationPage="/MainPage.xaml"/>
    </Tasks>
    <Tokens>
      <PrimaryToken TokenID="Your App token id" TaskName="_default">
        <TemplateType5>
          <BackgroundImageURI IsRelative="true" IsResource="false">Background.png</BackgroundImageURI>
          <Count>0</Count>
          <Title>Your app title</Title>
        </TemplateType5>
      </PrimaryToken>
    </Tokens>
  </App>
</Deployment>

The app, in the downloadable sample code, supports two configurations: a paid configuration and free with ads configuration. The main page title is set according to the DeploymentConfiguration.Paid property value, as shown in the following excerpt:

public MainPage()
{
    InitializeComponent();

    ApplicationTitle.Text = DeploymentConfiguration.Paid 
                                 ? "MY APP PRO" : "MY APP FREE";
}

This indicates the configuration of the application when the PAID preprocessor directive is changed in the DeploymentConfiguration class (see Figure 2).

Free App landing page Paid App landing page

Figure 2: The main page title changes according to the Paid property.

This enables you to verify that the app has indeed been built for a specific deployment scenario. More importantly, and in both cases, if you switch to the App List after deploying to the emulator you’ll see the application title updated to reflect the value in the generated WMAppManifest.xml file (see Figure 3).

Free App in App List Paid App in App List

Figure 3: App title reflects deployment scenario in the App List.

Thus, there is no longer any need to maintain two copies of your WMAppManifest.xml file or the entire project.

NOTE: The WMAppManifest.tt T4 template must be re-processed when the PAID directive is changed. This does not happen automatically. To rerun the T4 template right on the template and select Run Custom Tool. Alternative, use the Transform All Templates button in the Solution Explorer tool bar (see Figure 4).

Process All Templates Button

Figure 4: Process All Templates Button

If you wish, the preprocessor directive can be associated with a build configuration for your project, allowing you to switch to a different scenario without modifying the DeploymentConfiguration.cs file.

In this article you saw how to use a T4 template to generate the WMAppManifest.xml file for your app. You saw how a preprocessor directive can be used to change the contents of the WMAppManifest.xml file, in particular the application title to support different application deployment scenarios. The Visual Studio DTE was used to traverse the project structure to locate a property in a class; forming a bridge between the T4 template and your project configuration.

This approach allows you to maintain a single version of your app, and a single version of your WMAppManifest file. It’s an approach that I have found useful, and I hope you find it useful too.

Download Source Code (~40kb)

Follow me on twitter



Binding the WP7 ProgressIndicator in XAML

clock August 26, 2011 08:53 by author Daniel Vaughan

Update:

Since first posting this article, a later version of the WP FCL the ProgressIndicator gained binding support. You can bind it in a page like so:

<shell:SystemTray.ProgressIndicator>

        <shell:ProgressIndicator IsIndeterminate="{Binding Busy}" 

                                 IsVisible="{Binding Busy}" 

                                 Text="{Binding Message}" />

</shell:SystemTray.ProgressIndicator>

--------------------------------

 

The Mango beta of the Windows Phone 7 SDK sees the inclusion of a new way to display progress of asynchronous operations within the phone's system tray. This is done using the new ProgressIndicator class, which is a DependencyObject that hooks in to the native progress bar in the system tray, and allows you to display text message in the system tray, along with allowing you to control the progress bar that can handle both determinate and indeterminate states.

While the ProgressIndicator supports data-binding, the downside is that bindings need to be set up in the page code-beside; which is not very elegant. See the following example of a page constructor wiring up a ProgressIndicator:

 

public FooView()
{
    InitializeComponent();

    DataContext = new FooViewModel();

    Loaded += (o, args) =>
    {
        var progressIndicator = SystemTray.ProgressIndicator;

        if (progressIndicator != null)
        {
            return;
        }

        progressIndicator = new ProgressIndicator();

        SystemTray.SetProgressIndicator(this, progressIndicator);

        Binding binding = new Binding("Busy") { Source = ViewModel };

        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.IsVisibleProperty, binding);

        binding = new Binding("Busy") { Source = ViewModel };

        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.IsIndeterminateProperty, binding);

        binding = new Binding("Message") { Source = ViewModel };

        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.TextProperty, binding);
    };

}

 

While completing my latest chapter of Windows Phone 7 Unleashed, on local databases, I spent a few minutes writing a wrapper for the ProgressIndicator. The ProgressIndicatorProxy, as it's called, can be placed in XAML, and doesn't rely on any code-beside:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <u:ProgressIndicatorProxy IsIndeterminate="{Binding Indeterminate}" 
                                Text="{Binding Message}" 
                                Value="{Binding Progress}" />
</Grid>

 

The element itself has no visibility; its task is to attach a ProgressIndicator to the system tray, and to provide bindable properties that flow through to the ProgressIndicator instance.

When the element's Loaded event is raised, it instantiates a ProgressIndicator, assigns it to the system tray, and binds its properties to the ProgressIndicatorProxy objects properties. The class is shown in the following excerpt:

public class ProgressIndicatorProxy : FrameworkElement
{
    bool loaded;

    public ProgressIndicatorProxy()
    {
        Loaded += OnLoaded;
    }

    void OnLoaded(object sender, RoutedEventArgs e)
    {
        if (loaded)
        {
            return;
        }

        Attach();

        loaded = true;
    }

    public void Attach()
    {
        if (DesignerProperties.IsInDesignTool)
        {
            return;
        }

        var page = this.GetVisualAncestors<PhoneApplicationPage>().First();

        var progressIndicator = SystemTray.ProgressIndicator;
        if (progressIndicator != null)
        {
            return;
        }

        progressIndicator = new ProgressIndicator();

        SystemTray.SetProgressIndicator(page, progressIndicator);

        Binding binding = new Binding("IsIndeterminate") { Source = this };
        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.IsIndeterminateProperty, binding);

        binding = new Binding("IsVisible") { Source = this };
        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.IsVisibleProperty, binding);

        binding = new Binding("Text") { Source = this };
        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.TextProperty, binding);

        binding = new Binding("Value") { Source = this };
        BindingOperations.SetBinding(
            progressIndicator, ProgressIndicator.ValueProperty, binding);
    }

    #region IsIndeterminate

    public static readonly DependencyProperty IsIndeterminateProperty
        = DependencyProperty.RegisterAttached(
            "IsIndeterminate",
            typeof(bool),
            typeof(ProgressIndicatorProxy), new PropertyMetadata(false));

    public bool IsIndeterminate
    {
        get
        {
            return (bool)GetValue(IsIndeterminateProperty);
        }
        set
        {
            SetValue(IsIndeterminateProperty, value);
        }
    }

    #endregion

    #region IsVisible

    public static readonly DependencyProperty IsVisibleProperty
        = DependencyProperty.RegisterAttached(
            "IsVisible",
            typeof(bool),
            typeof(ProgressIndicatorProxy), new PropertyMetadata(true));

    public bool IsVisible
    {
        get
        {
            return (bool)GetValue(IsVisibleProperty);
        }
        set
        {
            SetValue(IsVisibleProperty, value);
        }
    }

    #endregion

    #region Text

    public static readonly DependencyProperty TextProperty
        = DependencyProperty.RegisterAttached(
            "Text",
            typeof(string),
            typeof(ProgressIndicatorProxy), new PropertyMetadata(string.Empty));

    public string Text
    {
        get
        {
            return (string)GetValue(TextProperty);
        }
        set
        {
            SetValue(TextProperty, value);
        }
    }

    #endregion

    #region Value

    public static readonly DependencyProperty ValueProperty
        = DependencyProperty.RegisterAttached(
            "Value",
            typeof(double),
            typeof(ProgressIndicatorProxy), new PropertyMetadata(0.0));

    public double Value
    {
        get
        {
            return (double)GetValue(ValueProperty);
        }
        set
        {
            SetValue(ValueProperty, value);
        }
    }

    #endregion
}

 

The sample code included with this post, contains a viewmodel with three properties, as listed:

  • Indeterminate, a Boolean that provides the IsIndeterminate value of the ProgressIndicator.
  • Progress: a double that is the source property of the Value property of the ProgressIndicator. This takes effect when the ProgressIndicator.IsIndeterminate property is true.
  • Message: a string value displayed via the ProgressIndicator.

The page is bound to an instance of the MainPageViewModel. The ProgressIndicatorProxy binds to the three viewmodel properties. In addition, a ToggleSwitch is used to control the indeterminate state of the ProgressIndicator via the Indeterminate property in the viewmodel, and a Slider controls the ProgressIndicator's Value property in the same manner. See the following excerpt:

<u:ProgressIndicatorProxy IsIndeterminate="{Binding Indeterminate}" 
                            Text="{Binding Message}" 
                            Value="{Binding Progress}" />

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <StackPanel>
        <toolkit:ToggleSwitch 
            IsChecked="{Binding Indeterminate, Mode=TwoWay}" 
            Header="Indeterminate" />

        <Slider Value="{Binding Progress, Mode=TwoWay}"
                Maximum="1" LargeChange=".2" />
    </StackPanel>
</Grid>

 

The sample page is shown in Figure 1.

 

Progress indicator proxy screenshot

Figure 1: ProgressIndicator is controlled via a XAML binding.

 

Note that there is no requirement to use the MVVM infrastructure located in the sample. And that the ProgressIndicatorProxy is entirely independent. I will, however, be releasing Calcium for Windows Phone 7 soon, which contains a cavalcade of useful components for building MVVM apps for WP7.

The custom ProgressIndicatorProxy provides a simple way to harness the new ProgressIndicator from your XAML. I hope you find it useful.

ProgressIndicatorProxyExample.zip (767.78 kb)

 

If you are interested in up-to-the-minute WP7 info, check out the Windows Phone Experts group on LinkedIn.

 

Follow me on twitter

 



Loading Data when the User Scrolls to the End of a List in Windows Phone 7

clock January 24, 2011 22:18 by author Daniel Vaughan

Most phone users are concerned about network usage. Network traffic comes at a premium, and a user's perception of the quality of your app depends a lot on its responsiveness. When it comes to fetching data from a network service, it should be done in the most efficient manner possible. Making the user wait while your app downloads giant reams of data doesn't cut it. It should, instead, be done in bite-sized chunks.

To make this easy for you, I have created a ScrollViewerMonitor which uses an attached property to monitor a ListBox and fetch data as the user needs it. It's as simple as adding an attached property to a control which contains a ScrollViewer, such as a ListBox, as shown in the following example:

<ListBox ItemsSource="{Binding Items}"
         u:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}" />

Notice the AtEndCommand. That's an attached property that allows you to specify a command to be executed when the user scrolls to the end of the list. Easy huh! I'll explain in a moment how this is accomplished, but first some background.

Background

For almost the last year, I've been building infrastructure for WP7 development. A lot has been going into the book I am writing, and even more is making its way into the upcoming Calcium for Windows Phone. I am pretty much at bursting point; wanting to get this stuff out there.

The chapter of Windows Phone 7 Unleashed, which discusses this code, demonstrates an Ebay search app that makes use of the Ebay OData feed (see Figure 1). It's simple, yet shows off some really nice techniques for handling asynchronous network calls.

Figure 1: The Ebay Seach app from Windows Phone 7 Unleashed.

 

The Ebay app isn't in the downloadable code for this post. But there is a simpler app that displays a list of numbers instead.

The way the ScrollViewerMonitor works is by retrieving the first child ScrollViewer control from its target (a ListBox in this case). It then listens to its VerticalOffset property for changes. When a change occurs, and the ScrollableHeight of the scrollViewer is the same as the VerticalOffset, the AtEndCommand is executed.

 

public class ScrollViewerMonitor
{
    public static DependencyProperty AtEndCommandProperty
        = DependencyProperty.RegisterAttached(
            "AtEndCommand"typeof(ICommand),
            typeof(ScrollViewerMonitor),
            new PropertyMetadata(OnAtEndCommandChanged));

    public static ICommand GetAtEndCommand(DependencyObject obj)
    {
        return (ICommand)obj.GetValue(AtEndCommandProperty);
    }

    public static void SetAtEndCommand(DependencyObject obj, ICommand value)
    {
        obj.SetValue(AtEndCommandProperty, value);
    }


    public static void OnAtEndCommandChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        FrameworkElement element = (FrameworkElement)d;
        if (element != null)
        {
            element.Loaded -= element_Loaded;
            element.Loaded += element_Loaded;
        }
    }

    static void element_Loaded(object sender, RoutedEventArgs e)
    {
        FrameworkElement element = (FrameworkElement)sender;
        element.Loaded -= element_Loaded;
        ScrollViewer scrollViewer = FindChildOfType<ScrollViewer>(element);
        if (scrollViewer == null)
        {
            throw new InvalidOperationException("ScrollViewer not found.");
        }

        var listener = new DependencyPropertyListener();
        listener.Changed
            += delegate
            {
                bool atBottom = scrollViewer.VerticalOffset
                                    >= scrollViewer.ScrollableHeight;

                if (atBottom)
                {
                    var atEnd = GetAtEndCommand(element);
                    if (atEnd != null)
                    {
            atEnd.Execute(null);
                    }                   
                }
            };
        Binding binding = new Binding("VerticalOffset") { Source = scrollViewer };
        listener.Attach(scrollViewer, binding);
    }

    static T FindChildOfType<T>(DependencyObject root) where T : class
    {
        var queue = new Queue<DependencyObject>();
        queue.Enqueue(root);

        while (queue.Count > 0)
        {
            DependencyObject current = queue.Dequeue();
            for (int i = VisualTreeHelper.GetChildrenCount(current) - 1; 0 <= i; i--)
            {
                var child = VisualTreeHelper.GetChild(current, i);
                var typedChild = child as T;
                if (typedChild != null)
                {
                    return typedChild;
                }
                queue.Enqueue(child);
            }
        }
        return null;
    }
}

 

Of course there is a little hocus pocus that goes on behind the scenes. The VerticalOffset property is a dependency property, and to monitor it for changes I've borrowed some of Pete Blois's code, which allows us to track any dependency property for changes. This class is called BindingListener and is in the downloadable sample code.

Sample Code

The ViewModel for the MainPage contains a FetchMoreDataCommand. When executed, this command sets a Busy flag, and waits a little while, then adds some more items to the ObservableCollection that the ListBox in the view is data-bound too.

Snippet

public class MainPageViewModel : INotifyPropertyChanged
{
    public MainPageViewModel()
    {
        AddMoreItems();

        fetchMoreDataCommand = new DelegateCommand(
            obj =>
                {
                    if (busy)
                    {
                        return;
                    }
                    Busy = true;
                    ThreadPool.QueueUserWorkItem(
                        delegate
                        {
                            /* This is just to demonstrate a slow operation. */
                            Thread.Sleep(3000);
                            /* We invoke back to the UI thread. 
                                * Ordinarily this would be done 
                                * by the Calcium infrastructure automatically. */
                            Deployment.Current.Dispatcher.BeginInvoke(
                                delegate
                                {
                                    AddMoreItems();
                                    Busy = false;
                                });
                        });
                    
            });
    }

    void AddMoreItems()
    {
        int start = items.Count;
        int end = start + 10;
        for (int i = start; i < end; i++)
        {
            items.Add("Item " + i);
        }
    }

    readonly DelegateCommand fetchMoreDataCommand;

    public ICommand FetchMoreDataCommand
    {
        get
        {
            return fetchMoreDataCommand;
        }
    }

    readonly ObservableCollection<string> items = new ObservableCollection<string>();

    public ObservableCollection<string> Items
    {
        get
        {
            return items;
        }
    }

    bool busy;

    public bool Busy
    {
        get
        {
            return busy;
        }
        set
        {
            if (busy == value)
            {
                return;
            }
            busy = value;
            OnPropertyChanged(new PropertyChangedEventArgs("Busy"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var tempEvent = PropertyChanged;
        if (tempEvent != null)
        {
            tempEvent(this, e);
        }
    }
}

 

There's a lot more infrastructure provided with the book code. But I tried hard to slim everything down for this post. The MainPage.xaml contains a Grid with a ProgressBar, whose visbility depends on the Busy property of the viewmodel.

Snippet

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <ListBox ItemsSource="{Binding Items}"
                u:ScrollViewerMonitor.AtEndCommand="{Binding FetchMoreDataCommand}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <Image Source="Images/WindowsPhoneExpertsLogo.jpg" 
                            Margin="10" />
                    <TextBlock Text="{Binding}" 
                                Style="{StaticResource PhoneTextTitle2Style}"/>                            
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <Grid Grid.Row="1"
            Visibility="{Binding Busy, 
                Converter={StaticResource BooleanToVisibilityConverter}}">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock Text="Loading..." 
                    Style="{StaticResource LoadingStyle}"/>
        <ProgressBar IsIndeterminate="{Binding Busy}"
                        VerticalAlignment="Bottom"
                        Grid.Row="1" />
    </Grid>
</Grid>

 

You may be wondering why there is a databinding for ProgressBar's IsIndeterminate property. This is for performance reasons, as when indeterminate the ProgressBar is notorious for consuming CPU. Check out Jeff Wilcox's blog for a solution.

Now, when the user scrolls to the bottom of the list, the FetchMoreDataCommand is executed, providing an opportunity to call some network service asynchronously (see Figure 2).

 

 

Figure 2: Loading message is displayed when the user scrolls to the end of the list.

 

I hope you enjoyed this post, and that you find the attached code useful.

If you are interested in up-to-the-minute WP7 info, check out the Windows Phone Experts group on LinkedIn.

 

DanielVaughan.ScrollViewerMonitor.zip (126.56 kb)

 

Follow me on twitter



ReaderWriterLockSlim: Conquering Mismatched Enter and Exit Calls

clock August 14, 2010 13:43 by author Daniel Vaughan

The ReaderWriterLockSlim class is used to protect a resource that is read by multiple threads and written to by one thread at a time. The class exists in the desktop FCL, but is noticeably absent from the Silverlight FCL. To readily support both platforms, some time ago, I incorporated the open-source mono implementation of the ReaderWriterLockSlim class into the Silverlight version of my core library, which is downloadable from http://calcium.codeplex.com/SourceControl/list/changesets

ReaderWriterLockSlim is a light-weight alternative to the Monitor class, for providing for concurrency. I say light-weight because the Monitor class only provides for exclusive access; where only a single thread can enter, regardless of the kind of operation.

The Monitor class, however, has an advantage: its syntax can be simplified using the lock statement, as shown in the following code snippet:

System.Object resourceLock = new System.Object();
System.Threading.Monitor.Enter(resourceLock);
try
{
DoSomething();
}
finally
{
System.Threading.Monitor.Exit(resourceLock);
}

 

Which is equivalent to the following, when using a lock statement:

lock (x)
{
DoSomething();
}

 

Using the lock statement means that we never get caught out forgetting to exit the lock, which could lead to a thread being blocked indefinitely.

No such baked-in infrastructure exists for the ReaderWriterLockSlim. So, I've created a number of extension methods to simulate the lock statement for the ReaderWriterLockSlim.

Using Extension Methods to Simulate Lock Syntax

If you've used the ReaderWriterLockSlim a lot, you'll know that mismatching Enter and Exit calls can be easy to do, especially when pasting code. For example, in the following excerpt we see how a call to enter a write protected section of code is mismatched with a call to exit a read section:

ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();

try
{
lockSlim.EnterWriteLock();
DoSomething();
}
finally
{
lockSlim.ExitReadLock();
}

 

This code will result in a System.Threading. SynchronizationLockException being raised.

The extension methods that have been written, allow a Func or an Action to be supplied, which will be performed within a try/finally block. The previous excerpt can be rewritten more concisely as:

ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();
lockSlim.PerformUsingWriteLock(() => DoSomething);

 

In the downloadable code I have included a unit test to demonstrate how the ReaderWriterLockSlim extension methods are used, (see Listing 1).

Listing 1: LockSlimTests Class

[TestClass]
public class LockSlimTests : SilverlightTest
{
readonly static List<string> sharedList = new List<string>();

[TestMethod]
public void ExtensionsShouldPerformActions()
{
ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();

string item1 = "test";

// Rather than this code:
// try
// {
// lockSlim.EnterWriteLock();
// sharedList.Add(item1);
// }
// finally
// {
// lockSlim.ExitWriteLock();
// }
// We can write this one liner:
lockSlim.PerformUsingWriteLock(() => sharedList.Add(item1));

// Rather than this code:
// string result;
// try
// {
// lockSlim.EnterReadLock();
// result = sharedList[0];
// }
// finally
// {
// lockSlim.ExitReadLock();
// }
// We can write this one liner:
string result = lockSlim.PerformUsingReadLock(() => sharedList[0]);

Assert.AreEqual(item1, result);

string item2 = "test2";

// Rather than this code:
// try
// {
// lockSlim.EnterUpgradeableReadLock();
// if (!sharedList.Contains(item2))
// {
// try
// {
// lockSlim.EnterWriteLock();
// sharedList.Add(item2);
// }
// finally
// {
// lockSlim.ExitWriteLock();
// }
// }
// }
// finally
// {
// lockSlim.ExitUpgradeableReadLock();
// }
// We can write this:
lockSlim.PerformUsingUpgradeableReadLock(() =>
{
if (!sharedList.Contains(item2))
{
lockSlim.PerformUsingWriteLock(() => sharedList.Add(item2));
}
});

// Rather than this code:
// try
// {
// lockSlim.EnterReadLock();
// result = sharedList[1];
// }
// finally
// {
// lockSlim.ExitReadLock();
// }
// We can write this:
result = lockSlim.PerformUsingReadLock(() => sharedList[1]);

Assert.AreEqual(item2, result);
}

}

 

The result of executing this test is shown in Figure 1.

 

Figure 1: Result of running the ReaderWriterLockSlimExtension tests.

 

The ReaderWriterLockSlimExtensions accept a simple Action or a Func to return value, and take care of calling the appropriate Enter and Exit methods, inside a try/finally block, (see Listing 2).

Listing 2: ReaderWriterLockSlimExtensions Class

public static class ReaderWriterLockSlimExtensions
{
public static void PerformUsingReadLock(this ReaderWriterLockSlim readerWriterLockSlim, Action action)
{
ArgumentValidator.AssertNotNull(readerWriterLockSlim, "readerWriterLockSlim");
ArgumentValidator.AssertNotNull(action, "action");
try
{
readerWriterLockSlim.EnterReadLock();
action();
}
finally
{
readerWriterLockSlim.ExitReadLock();
}
}

public static T PerformUsingReadLock<T>(this ReaderWriterLockSlim readerWriterLockSlim, Func<T> action)
{
ArgumentValidator.AssertNotNull(readerWriterLockSlim, "readerWriterLockSlim");
ArgumentValidator.AssertNotNull(action, "action");
try
{
readerWriterLockSlim.EnterReadLock();
return action();
}
finally
{
readerWriterLockSlim.ExitReadLock();
}
}

public static void PerformUsingWriteLock(this ReaderWriterLockSlim readerWriterLockSlim, Action action)
{
ArgumentValidator.AssertNotNull(readerWriterLockSlim, "readerWriterLockSlim");
ArgumentValidator.AssertNotNull(action, "action");
try
{
readerWriterLockSlim.EnterWriteLock();
action();
}
finally
{
readerWriterLockSlim.ExitWriteLock();
}
}

public static T PerformUsingWriteLock<T>(this ReaderWriterLockSlim readerWriterLockSlim, Func<T> action)
{
ArgumentValidator.AssertNotNull(readerWriterLockSlim, "readerWriterLockSlim");
ArgumentValidator.AssertNotNull(action, "action");
try
{
readerWriterLockSlim.EnterWriteLock();
return action();
}
finally
{
readerWriterLockSlim.ExitWriteLock();
}
}

public static void PerformUsingUpgradeableReadLock(this ReaderWriterLockSlim readerWriterLockSlim, Action action)
{
ArgumentValidator.AssertNotNull(readerWriterLockSlim, "readerWriterLockSlim");
ArgumentValidator.AssertNotNull(action, "action");
try
{
readerWriterLockSlim.EnterUpgradeableReadLock();
action();
}
finally
{
readerWriterLockSlim.ExitUpgradeableReadLock();
}
}

public static T PerformUsingUpgradeableReadLock<T>(this ReaderWriterLockSlim readerWriterLockSlim, Func<T> action)
{
ArgumentValidator.AssertNotNull(readerWriterLockSlim, "readerWriterLockSlim");
ArgumentValidator.AssertNotNull(action, "action");
try
{
readerWriterLockSlim.EnterUpgradeableReadLock();
return action();
}
finally
{
readerWriterLockSlim.ExitUpgradeableReadLock();
}
}
}

 

The ArgumentValidator class is present in my base library. Calls to its AssertNotNull can be replaced with a null check, and if null throw an ArgumentNullException. If you'd like the code for the ArgumentValidator etc., you can find it in the Core class library in the source available at http://calcium.codeplex.com/SourceControl/list/changesets

Conclusion

In this post we have seen how extension methods can be used to ensure that the ReaderWriterLockSlim class is correctly exited after a thread critical region. This avoids the problem of mismatched Enter and Exit calls, which can result in exceptions and indefinite blocking.

I hope you have enjoyed this post, and that you find the code and ideas presented within it useful.

 

Download code: ReaderWriterLockSlimExtensions.zip (1.14 mb)



Enforcing Single Instance WPF Applications

clock August 1, 2010 17:39 by author Daniel Vaughan

Introduction

Today the WPF Disciples, and in particular my good friend and fellow WPF Disciple, Pete O'Hanlon, were sitting around the proverbial campfire, discussing how to enforce single instance WPF apps, for Pete's cool Goldlight project. By single instance WPF apps, I mean limiting an executable to only one instance in execution. This can be useful in scenarios where multiple application instances may play havoc with shared state. I took some time away from writing my book, to see if I could come up with something usable.

Building a Single Instance Application Enforcer

The singleton application model works like this:

  1. User starts app1.
  2. User starts app2.
  3. App2 detects app1 is running.
  4. App2 quits.

 

There is, however, a second part to our challenge, as Pete pointed out. What happens if we wish to pass some information from app2 to app1 before app2 quits? If, for example, the application is associated with a particular file type, and the user happens to double click on a file of that type, then we would have app2 tell app1 what file the user was trying to open.

To accomplish this we need a means to communicate between the two application instances. There are a number of approaches that could be taken, and some include:

  • Named pipes
  • Sending a message to the main application's window with a native API call
  • MemoryMappedFile

I chose to go for the MemoryMappedFile, along with an EventWaitHandle. The consensus by the Disciples was for a Mutex (not an EventWaitHandle), but the Mutex turned out not to provide for the initial signaling that I needed. I have encapsulated the logic for the singleton application enforcement, into a class called SingletonApplicationEnforcer (see Listing 1). The class instantiates the EventWaitHandle, and informs the garbage collector via the GC.KeepAlive method, that it should not be garbage collected. If this is the only application that has instantiated the EventWaitHandle with the specified name, then the createdNew argument will be set to true. This is how we determine, if the application is the singleton application.

Listing 1: SingletonApplicationEnforcer Class

/// <summary>
/// This class allows restricting the number of executables in execution, to one.
/// </summary>
public sealed class SingletonApplicationEnforcer
{
    readonly Action<IEnumerable<string>> processArgsFunc;
    readonly string applicationId;
    Thread thread;
    string argDelimiter = "_;;_";

    /// <summary>
    /// Gets or sets the string that is used to join 
    /// the string array of arguments in memory.
    /// </summary>
    /// <value>The arg delimeter.</value>
    public string ArgDelimeter
    {
        get
        {
            return argDelimiter;
        }
        set
        {
            argDelimiter = value;
        }
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="SingletonApplicationEnforcer"/> class.
    /// </summary>
    /// <param name="processArgsFunc">A handler for processing command line args 
    /// when they are received from another application instance.</param>
    /// <param name="applicationId">The application id used 
    /// for naming the <seealso cref="EventWaitHandle"/>.</param>
    public SingletonApplicationEnforcer(Action<IEnumerable<string>> processArgsFunc, 
        string applicationId = "DisciplesRock")
    {
        if (processArgsFunc == null)
        {
            throw new ArgumentNullException("processArgsFunc");
        }
        this.processArgsFunc = processArgsFunc;
        this.applicationId = applicationId;
    }

    /// <summary>
    /// Determines if this application instance is not the singleton instance.
    /// If this application is not the singleton, then it should exit.
    /// </summary>
    /// <returns><c>true</c> if the application should shutdown, 
    /// otherwise <c>false</c>.</returns>
    public bool ShouldApplicationExit()
    {
        bool createdNew;
        string argsWaitHandleName = "ArgsWaitHandle_" + applicationId;
        string memoryFileName = "ArgFile_" + applicationId;

        EventWaitHandle argsWaitHandle = new EventWaitHandle(
            false, EventResetMode.AutoReset, argsWaitHandleName, out createdNew);

        GC.KeepAlive(argsWaitHandle);

        if (createdNew)
        {
            /* This is the main, or singleton application. 
                * A thread is created to service the MemoryMappedFile. 
                * We repeatedly examine this file each time the argsWaitHandle 
                * is Set by a non-singleton application instance. */
            thread = new Thread(() =>
                {
                    try
                    {
                        using (MemoryMappedFile file = MemoryMappedFile.CreateOrOpen(memoryFileName, 10000))
                        {
                            while (true)
                            {
                                argsWaitHandle.WaitOne();
                                using (MemoryMappedViewStream stream = file.CreateViewStream())
                                {
                                    var reader = new BinaryReader(stream);
                                    string args;
                                    try
                                    {
                                        args = reader.ReadString();
                                    }
                                    catch (Exception ex)
                                    {
                                        Debug.WriteLine("Unable to retrieve string. " + ex);
                                        continue;
                                    }
                                    string[] argsSplit = args.Split(new string[] { argDelimiter }, 
                                                                    StringSplitOptions.RemoveEmptyEntries);
                                    processArgsFunc(argsSplit);
                                }

                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine("Unable to monitor memory file. " + ex);
                    }
                });

            thread.IsBackground = true;
            thread.Start();
        }
        else
        {
            /* Non singleton application instance. 
                * Should exit, after passing command line args to singleton process, 
                * via the MemoryMappedFile. */
            using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(memoryFileName))
            {
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    var writer = new BinaryWriter(stream);
                    string[] args = Environment.GetCommandLineArgs();
                    string joined = string.Join(argDelimiter, args);
                    writer.Write(joined);
                }
            }
            argsWaitHandle.Set();
        }

        return !createdNew;
    }
}

If the process happens to be the singleton application, then a new thread is started that will block until it receives a signal (via the argsWaitHandle). This signal indicates that the MemoryMappedFile contains data to be read. It is non-singleton applications instances that perform this signalling, via the argsWaitHandle.Set method, after the string arguments have been written to the MemoryMappedFile.

Demonstrating the SingletonApplicationEnforcer Class

The downloadable code includes two solutions, and two projects. Each use the SingletonApplicationEnforcer class in their respective App (App.xaml.cs) classes. To try out the sample, open both solutions. Start debuging the SingleApp project first, and then launch the SingleApp2 project. What will hopefully result is that the SingleApp2 project will detect that it is not the singleton application, and it will write its command line arguments to a MemoryMappedFile. The SingleApp application will detect that data has been written to the file, and present the command line arguments in its main window (see Figure 1).

Figure 1: The demo application consists of a single window, which displays received command line arguments.

 

The entry point for either projects is the App class. It is in this class that we consume the SingletonApplicationEnforcer class, to detect whether the application should be allowed to execute (see Listing 2). The App classes constructor uses the SingletonApplicationEnforcer's ShouldApplicationExit method; which, as we saw in Listing 1, uses an EventWaitHandle to determine if it is the only instance in execution. If it isn't then the method returns true, and the application is explicitly shutdown.

Listing 2: App Class

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    readonly SingletonApplicationEnforcer enforcer = new SingletonApplicationEnforcer(DisplayArgs);

    public App()
    {
        if (enforcer.ShouldApplicationExit())
        {
            this.Shutdown();
        }
    }

    public static void DisplayArgs(IEnumerable<string> args)
    {
        foreach (var arg in args)
        {
            string message = string.Format("Received arg: {0}", arg);
            Debug.WriteLine(message);
        }
            
        var dispatcher = Current.Dispatcher;
        if (dispatcher.CheckAccess())
        {
            ShowArgs(args);
        }
        else
        {
            dispatcher.BeginInvoke(
                new Action(delegate
                {
                    ShowArgs(args);
                }));
        }
    }

    static void ShowArgs(IEnumerable<string> args)
    {
        var mainWindow = Current.MainWindow as MainWindow;
        if (mainWindow != null && args != null)
        {
            foreach (var arg in args)
            {
                mainWindow.ViewModel.Args.Add(arg);
            }
        }
    }

}

As usual, this application uses the MVVM pattern. The MainWindow has its DataContext property set to an instance of the MainWindowViewModel (see Listing 3).

Listing 3: MainWindow XAML

<Window x:Class="SingleApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Singleton Application Enforcer Example" 
        Height="350" Width="525" ResizeMode="NoResize" Background="Black">
    <StackPanel>
        <Image Source="Images/DisciplesBackground.jpg" />
        <StackPanel Margin="10">
            <TextBlock Text="Received Args:" FontSize="16" Padding="10" Foreground="White"/>
            <ListBox ItemsSource="{Binding Args}" 
                     VerticalAlignment="Stretch" Height="185" />
        </StackPanel>
    </StackPanel>
</Window>

The viewmodel (MainWindowViewModel), shown in Listing 2, exposes an ObsertableCollection of strings, that reflect arguments that are passed to the application, from other application instances.

Listing 4: MainWindowViewModel

public class MainWindowViewModel : INotifyPropertyChanged
{
    static ObservableCollection<string> args = new ObservableCollection<string>();

    public ObservableCollection<string> Args
    {
        get
        {
            return args;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        var temp = PropertyChanged;
        if (temp != null)
        {
            temp(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


Conclusion

In this post we have seen how a MemoryMappedFile can be used in conjunction with a EventWaitHandle, to provide for cross process communication in order to limit execution to a single application instance. We also saw how to communicate command line arguments to the singleton application, so that it can respond adequately to user intent.

I hope you enjoyed this post, and that you find the code and ideas presented here useful.

Download code: SingletonEnforcementV2.zip (345.05 kb)



ViewModel Active Awareness in a Prism Based Application

clock February 5, 2010 15:13 by author Daniel Vaughan

Yesterday, while chatting with the highly talented Jeremiah Morrill and other WPF Disciples about some MVVM subtleties (for the full post see here), Jeremiah briefly touched on the topic of providing ViewModels with the awareness of being active or inactive within a Prism based application. I wanted to explore this further, and decided to integrate this functionality into Calcium. What I provide here isn't rocket science, and merely serves to illustrate one of indeed many design approaches that could be applied to accomplish the same thing.

For this I had two goals. The first, to provide the capability without coupling the ViewModel to the View. That is, without requiring the ViewModel to have a reference to the View. The second, to not depend on a base class for the functionality; forever tying the developer to my base class implementation (ViewModelBase). So, indeed, I chose an interface based approach. To be Prism-esque I have adapted Jeremiah's approach which was to implement Prism's IActiveAware interface on my base view class. I then feed an intermediary object to the ViewModel via an interface named IViewAware. The intermediary object is an instance of ActiveAwareUIElementAdapter. This class is used to provide a UIElement instance with Prisms IActiveAware interface. It does so by monitoring its Got and LostFocus events.

 

ActiveAwareUIElementAdapter

 

/// <summary>
/// Wraps a <see cref="UIElement"/> to provide an <see cref="IActiveAware"/>
/// implementation based on its focus state.
/// </summary>
public class ActiveAwareUIElementAdapter : IActiveAware
{
    bool active;

    public ActiveAwareUIElementAdapter(UIElement uiElement)
    {
        ArgumentValidator.AssertNotNull(uiElement, "uiElement");
        uiElement.GotFocus += OnGotFocus;
        uiElement.LostFocus += OnLostFocus;
    }

    void OnLostFocus(object sender, RoutedEventArgs e)
    {
        IsActive = false;
    }

    void OnGotFocus(object sender, RoutedEventArgs e)
    {
        IsActive = true;
    }

    public bool IsActive
    {
        get
        {
            return active;
        }
        set
        {
            if (active != value)
            {
                active = value;
            }
            OnIsActiveChanged(EventArgs.Empty);
        }
    }

    #region event IsActiveChanged

    event EventHandler isActiveChanged;

    public event EventHandler IsActiveChanged
    {
        add
        {
            isActiveChanged += value;
        }
        remove
        {
            isActiveChanged -= value;
        }
    }

    protected void OnIsActiveChanged(EventArgs e)
    {
        if (isActiveChanged != null)
        {
            isActiveChanged(this, e);
        }
    }

    #endregion
}

We then use this class within any IView UIElement implementation, but in particular the base ViewControl class. We instantiate the ActiveAwareUIElement adapter within the view's constructor, and pass it the instance of the view itself. The ActiveAwareUIElement then simply subscribes to the GotFocus and LostFocus events of the view, which is of course a UIElement.

 

ViewControl Implementation

 

/// <summary>
/// The base class for <see cref="IView"/>s.
/// </summary>
public class ViewControl : UserControl, IView, IActiveAware /* (not abstract for Blendability) */
{
    #region ViewModel Dependency Property

    public static DependencyProperty ViewModelProperty = DependencyProperty.Register(
        "ViewModel", typeof(IViewModel), typeof(ViewControl), new PropertyMetadata(null, OnViewModelChanged));

    static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var viewControl = (ViewControl)d;
        viewControl.SetViewAwareAssociations((IViewModel)e.OldValue, (IViewModel)e.NewValue);
    }

    [Description("The view model for this view.")]
#if !SILVERLIGHT
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
#endif
    public IViewModel ViewModel
    {
        get
        {
            return (IViewModel)GetValue(ViewModelProperty);
        }
        set
        {
            SetValue(ViewModelProperty, value);
        }
    }

    #endregion

    /// <summary>
    /// Initializes a new instance of the <see cref="ViewControl"/> class.
    /// </summary>
    public ViewControl()
    {
        Loaded += OnLoaded;
        activeAwareUIElementAdapter = new ActiveAwareUIElementAdapter(this); 
    }

    bool alreadyLoaded;

    void OnLoaded(object sender, RoutedEventArgs e)
    {
        if (!alreadyLoaded)
        {
            alreadyLoaded = true;
            OnViewLoaded(e);
        }
    }

    #region ViewLoaded event

    event EventHandler<EventArgs> viewLoaded;

    /// <summary>
    /// Occurs when the view has been loaded.
    /// </summary>
    public event EventHandler<EventArgs> ViewLoaded
    {
        add
        {
            viewLoaded += value;
        }
        remove
        {
            viewLoaded -= value;
        }
    }

    /// <summary>
    /// Closes the view.
    /// </summary>
    /// <param name="force">if set to <c>true</c> the control will be forced
    /// to close even if e.g., there is unsaved data and the user chooses 
    /// to cancel the closure.</param>
    /// <returns></returns>
    public virtual bool Close(bool force)
    {
        var viewService = ServiceLocatorSingleton.Instance.GetInstance<IViewService>();
        return viewService.CloseView(this, force);
    }

    /// <summary>
    /// Raises the <see cref="E:ViewLoaded"/> event.
    /// </summary>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    protected void OnViewLoaded(EventArgs e)
    {
        if (viewLoaded != null)
        {
            viewLoaded(this, e);
        }
    }
    #endregion

    /// <summary>
    /// Gets a value indicating whether the control is in a designer.
    /// </summary>
    /// <value><c>true</c> if design time; otherwise, <c>false</c>.</value>
    protected bool DesignTime
    {
        get
        {
            return DesignerProperties.GetIsInDesignMode(this);
        }
    }

    #region IActiveAware and related

    void SetViewAwareAssociations(IViewModel oldViewModel, IViewModel newViewModel)
    {
        var oldViewAware = oldViewModel as IViewAware;
        var newViewAware = newViewModel as IViewAware;
        if (oldViewAware != null)
        {
            oldViewAware.DetachActiveAware();
        }

        if (newViewAware != null)
        {
            newViewAware.Attach(activeAwareUIElementAdapter);
        }
    }

    readonly ActiveAwareUIElementAdapter activeAwareUIElementAdapter;

    bool IActiveAware.IsActive
    {
        get
        {
            return activeAwareUIElementAdapter.IsActive;
        }
        set
        {
            activeAwareUIElementAdapter.IsActive = value;
        }
    }

    event EventHandler IActiveAware.IsActiveChanged
    {
        add
        {
            activeAwareUIElementAdapter.IsActiveChanged += value;
        }
        remove
        {
            activeAwareUIElementAdapter.IsActiveChanged -= value;
        }
    }

    #endregion
}

We see that the dependency property ViewModel, when changed, prompts the attachment of the ActiveAwareUIElement instance to the ViewModel. The mechanism for performing this is via the IViewAware implementation. If an IViewModel wishes to be aware of its view's state, in particular when it becomes active or inactive; without having to have a direct reference to the view, then it can implement the IViewAware interface.

 

IViewAware Interface


/// <summary>
/// Provides for advanced presentation behaviour in a <see cref="IViewModel"/>s.
/// </summary>
public interface IViewAware
{
    /// <summary>
    /// Attaches the specified active aware instance so that changes in the <see cref="IActiveAware.IsActive"/>
    /// state can be monitored.
    /// </summary>
    /// <param name="activeAware">The active aware.</param>
    void Attach(IActiveAware activeAware);

    /// <summary>
    /// Detaches the active aware instance. Changes in the <see cref="IActiveAware.IsActive"/>
    /// state will no longer be monitored.
    /// </summary>
    void DetachActiveAware();
}

The ViewModel base class implementation is provided next in full:

/// <summary>
/// A base implementation of the <see cref="IViewModel"/> interface.
/// </summary>
public abstract class ViewModelBase : IViewModel, INotifyPropertyChanged, IViewAware
{
    IActiveAware activeAwareInstance;

    protected ViewModelBase()
    {
        notifier = new PropertyChangeNotifier(this);
    }

    #region Title Property

    object title;

    [Description("The text to display on a tab.")]
#if !SILVERLIGHT
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
#endif        
    public object Title
    {
        get
        {
            return title;
        }
        set
        {
            notifier.Assign("Title", ref title, value);
        }
    }

    #endregion

    #region Property Change Notification
    readonly PropertyChangeNotifier notifier;

    protected PropertyChangeNotifier Notifier
    {
        get
        {
            return notifier;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            notifier.PropertyChanged += value;
        }
        remove
        {
            notifier.PropertyChanged -= value;
        }
    }

    protected AssignmentResult Assign<TProperty>(
        string propertyName, ref TProperty property, TProperty newValue)
    {
        return notifier.Assign(propertyName, ref property, newValue);
    }

    #endregion

    #region Active Aware

    void IViewAware.Attach(IActiveAware activeAware)
    {
        ReplaceActiveAware(activeAware);
    }

    void IViewAware.DetachActiveAware()
    {
        ReplaceActiveAware(null);
    }

    void ReplaceActiveAware(IActiveAware activeAwareInstance)
    {
        if (this.activeAwareInstance != null)
        {
            this.activeAwareInstance.IsActiveChanged -= OnIsActiveChanged;
        }
        this.activeAwareInstance = activeAwareInstance;
        if (activeAwareInstance != null)
        {
            activeAwareInstance.IsActiveChanged += OnIsActiveChanged;
        }
    }

    bool lastActiveState;

    void OnIsActiveChanged(object sender, EventArgs e)
    {
        Notifier.NotifyChanged("Active", lastActiveState, Active);
        lastActiveState = Active;
    }

    /// <summary>
    /// Gets a value indicating whether this instance is being notified 
    /// of when it becomes active or inactive, 
    /// this may occur for example when its view gains focus or loses focus.
    /// </summary>
    /// <value><c>true</c> if monitoring the active state 
    /// of its view; otherwise, <c>false</c>.</value>
    public bool ActiveAware
    {
        get
        {
            return activeAwareInstance != null;
        }
    }

    /// <summary>
    /// Gets a value indicating whether this <see cref="ViewModelBase"/> 
    /// is active within the user interface.
    /// </summary>
    /// <value><c>true</c> if active; otherwise, <c>false</c>.</value>
    public bool Active
    {
        get
        {
            return activeAwareInstance != null ? activeAwareInstance.IsActive : false;
        }
    }

    #endregion

    public override string ToString()
    {
        return title != null ? title.ToString() : base.ToString();
    }
}

So there it is. Just one way to provide a ViewModel with active awareness. Please be aware that this code is preliminary and may be subject to change. The full source code will be available via the Calcium source download page soon.

 

Thanks to Kent Boogaart for his post on MVVM Infrastructure ActiveAwareCommand which the ActiveAwareUIElementAdapter was inspired from.



Synchronous Invocation of Delegates with the Silverlight Dispatcher

clock January 10, 2010 18:14 by author Daniel Vaughan

Introduction

In this post I would like to briefly discuss the System.Windows.Threading.Dispatcher class, and the significant differences between its Silverlight and Desktop CLR implementations. We are going to look at solving two things:

  1. Consuming the UI’s Dispatcher in Silverlight before a page has been instanciated.
  2. Allowing for synchronous invocation of delegates on the UI thread.

Background

Recently my good friend Sacha Barber published an article, and in the comments of which we briefly touched on a cross threading issue that we have both experienced with the Silverlight Dispatcher class. I thought it was about time that I wrote some of this stuff up. This is the result.

Silverlight Thread Affinity

When working with Silverlight, one has to contend with the usual single threaded apartment model (STA) that is also present when working with WPF or Windows Forms. This means that one must interact with UI components, in particular DependencyObject derived types, from the thread in which they were created on. Fortunately Silverlight/WPF/Windows Forms includes infrastructure that makes acquiring and invoking calls on the UI thread simpler; specifically the System.Windows.Threading.Dispatcher, which is a prioritized message loop that handles thread affinity.

There is an excellent article describing the Dispatcher in detail.

Consuming the UI’s Dispatcher

In Silverlight a Dispatcher becomes associated with the main page during initialization, thereby making it available via the Applications RootVisual property like so:

Application.Current.RootVisual.Dispatcher

We can consume the Dispatcher this way, as long as we do so after the RootVisual has been defined. But in the case where we would like to consume the Dispatcher from the get-go, it leaves us out in the cold. Fortunately though, the Silverlight Dispatcher instance is also available via the System.Windows.Deployment.Current.Dispatcher property. This instance is defined when the Application starts, thereby making it possible to commence asynchronous operations before the first page is instanciated.

Synchronous Invocation of Delegates on the UI Thread

The Silverlight Dispatcher is geared for asynchronous operations. As we can see from the following image, unlike the Desktop CLR Dispatcher, the Silverlight Dispatcher class’s Invoke method overloads have internal visibility.

It has to be said that the Desktop CLR Dispatcher, when compared with the Silverlight version, as with many other classes, has a much richer API. In order to provide a means to synchronously invoke a delegate on the UI thread we need another approach. The approach I have taken is to utilize the System.Windows.Threading.DispatcherSynchronizationContext

By using the Post and Send methods of the DispatcherSynchronizationContext we are able to regain the synchronous Invoke capabilities within the Silverlight environment.

I have rolled this up into a set of reusable classes, located in my core Silverlight library, which you can find in the DanielVaughan.Silverlight project in the Calcium http://www.calciumsdk.net download.

/// <summary>
/// Singleton class providing the default implementation 
/// for the <see cref="ISynchronizationContext"/>, specifically for the UI thread.
/// </summary>
public class UISynchronizationContext : ISynchronizationContext
{
    DispatcherSynchronizationContext context;
    Dispatcher dispatcher;
    
    #region Singleton implementation

    static readonly UISynchronizationContext instance = new UISynchronizationContext();
    
    /// <summary>
    /// Gets the singleton instance.
    /// </summary>
    /// <value>The singleton instance.</value>
    public static ISynchronizationContext Instance
    {
        get
        {
            return instance;
        }
    }

    #endregion

    public void Initialize()
    {
        EnsureInitialized();
    }

    readonly object initializationLock = new object();

    void EnsureInitialized()
    {
        if (dispatcher != null && context != null)
        {
            return;
        }

        lock (initializationLock)
        {
            if (dispatcher != null && context != null)
            {
                return;
            }

            try
            {
                dispatcher = Deployment.Current.Dispatcher;
                context = new DispatcherSynchronizationContext(dispatcher);
            }
            catch (InvalidOperationException)
            {
                /* TODO: Make localizable resource. */
                throw new ConcurrencyException("Initialised called from non-UI thread."); 
            }
        }
    }

    public void Initialize(Dispatcher dispatcher)
    {
        ArgumentValidator.AssertNotNull(dispatcher, "dispatcher");
        lock (initializationLock)
        {
            this.dispatcher = dispatcher;
            context = new DispatcherSynchronizationContext(dispatcher);
        }
    }

    public void InvokeAsynchronously(SendOrPostCallback callback, object state)
    {
        ArgumentValidator.AssertNotNull(callback, "callback");
        EnsureInitialized();

        context.Post(callback, state);
    }

    public void InvokeAsynchronously(Action action)
    {
        ArgumentValidator.AssertNotNull(action, "action");
        EnsureInitialized();

        if (dispatcher.CheckAccess())
        {
            action();
        }
        else
        {
            dispatcher.BeginInvoke(action);
        }
    }

    public void InvokeSynchronously(SendOrPostCallback callback, object state)
    {
        ArgumentValidator.AssertNotNull(callback, "callback");
        EnsureInitialized();

        context.Send(callback, state);
    }

    public void InvokeSynchronously(Action action)
    {
        ArgumentValidator.AssertNotNull(action, "action");
        EnsureInitialized();

        if (dispatcher.CheckAccess())
        {
            action();
        }
        else
        {
            context.Send(delegate { action(); }, null);
        }
    }

    public bool InvokeRequired
    {
        get
        {
            EnsureInitialized();
            return !dispatcher.CheckAccess();
        }
    }
}

A further advantage of using either a Silverlight or Desktop CLR implementation of the ISynchronizationContext is that we are able to write CLR agnostic code. That is, code that was written for the Desktop CLR can be easily moved to the Silverlight.

Using the code:

UISynchronizationContext.Instance.InvokeSynchronously(delegate
                                {
/* Code to execute on the UI thread. */
                                });

Conclusion

In this post we have looked at consuming the UI’s Dispatcher in Silverlight as soon as an Application starts. We also saw how it is possible in Silverlight to accomplish synchronous invocation of delegates on the UI thread.

The full source shown in this article is available on the Calcium Codeplex site

 

 

 



Using T4 to Generate Pack URIs for XAML Files

clock November 25, 2009 15:25 by author Daniel Vaughan

Yesterday my fellow WPF Disciple Paul Stovell got me thinking about resolving XAML file paths.

As Paul points out, there doesn't appear to be an easy way to locate the URI for a XAML file. Internally, the generated .g.cs makes use of the path, as shown in the following excerpt:

public void InitializeComponent() 
{ 
  if (_contentLoaded) 
  { 
    return; 
  } 
  _contentLoaded = true; 
  System.Uri resourceLocater = new System.Uri("/PageCollection;component/pages/page1.xaml", System.UriKind.Relative); 
  #line 1 "..\..\..\Pages\Page1.xaml" 
  System.Windows.Application.LoadComponent(this, resourceLocater); 
  #line default 
  #line hidden 
}

But, how can we get our hands on it? What I’ve done is to incorporate the generation of XAML resource pack URIs into the T4 template I did a little while ago.

To demonstrate I have created a dummy UserControl in a subfolder in the sample application.

Image Figure: Dummy UserControl has a pack URI generated

 

The resulting output from the T4 template now enables us to determine the path to the XAML file in a safe way. The following excerpt shows the generated Pack URI:

namespace CSharpDesktopClrDemo.XamlMetadata.Folder1.Folder2.Metadata
{
    /// <summary>Metadata for XAML UserControl1.xaml</summary>
    public static class UserControl1XamlMetadata
    {
            /// <summary>Resource pack URI for XAML file.</summary>
            public const string XamlPackUri 
= @"/DanielVaughan.MetaGen.Demo;component/Folder1/Folder2/UserControl1.xaml"; } }

Now we have this, we can write:

Uri uri = new Uri(CSharpDesktopClrDemo.XamlMetadata.Folder1.Folder2.Metadata
                 .UserControl1XamlMetadata.XamlPackUri, UriKind.Relative);
var control = System.Windows.Application.LoadComponent(uri) 
       as DanielVaughan.MetaGen.Demo.Folder1.Folder2.UserControl1;

No more magic string pack URIs!

Download the template and sample application: MetaGen_01_04.zip (393.35 kb)

 



Order the Book

Ready to take your Windows Phone development skills to the next level? My book is the first comprehensive, start-to-finish developer's guide to Microsoft's Windows Phone 8. In it I teach through complete sample apps that illuminate each key concept with fully explained code and real-world context. Order Windows Phone 8 Unleashed

Windows Phone Experts Windows Phone Experts
LinkedIn Group

 

Bio

Daniel VaughanDaniel Vaughan is cofounder and president of Outcoder, a Swiss software and consulting company dedicated to creating best-of-breed user experiences and leading-edge back-end solutions, using the Microsoft stack of technologies--in particular Silverlight, WPF, WinRT, and Windows Phone.

He is a Microsoft MVP for Client Application Development, with more than a decade of commercial experience across a wide range of industries including finance, e-commerce, and multimedia.

Daniel is also the author of Windows Phone 7.5 Unleashed, the first comprehensive, start-to-finish developer's guide to Microsoft's Windows Phone 7.5.

Daniel is a Silverlight and WPF Insider, a member of the elite WPF Disciples group, and threetime CodeProject MVP.

Daniel is also the creator of a number of open-source projects, including Calcium, and Clog. E-mail me Send mail

 

Microsoft MVP logo Disciple
WPF and Silverlight Insiders
 

 

 

Sign in