Cimbalino Windows Phone Toolkit: MultiApplicationBarBehavior

My previous article showed how to use the ApplicationBarBehavior from the Cimbalino Windows Phone Toolkit to build applications with MVVM pattern and still use the Application Bar control without the need for any code-behind.

More than just controlling the app bar from the ViewModel, the ApplicationBarBehavior adds some nice new properties that you can’t find in the native app bar control.

Such is the nature of the IsVisible property found in the buttons and menu items, allowing to change the app bar contents with some ease!

To demonstrate the IsVisible property, I’ll use the sample code from the previous article: this will generate an app bar with 3 buttons, the first two will appear when IsSelectionDisabled = true and the 3rd one will appear when IsSelectionEnabled = true (the opposite state).

This is the recorded animation of what the state changing causes to the application bar buttons visibility:

ApplicationBarBehavior

As you can see, it works perfectly! Well, almost perfectly…

If you look really closely, you’ll notice that the animation doesn’t seem quite that smooth!

By making time go a bit slower, this is what is actually happening:

ApplicationBarBehavior (Slower)

As you can see above, the buttons move before the animation starts!

This behavior is due to the nature of the ApplicationBar.Buttons and ApplicationBar.MenuItems collections: their type is IList, and as such, all we really have is the Add, Remove and Clear methods to manipulate the collection items.

And that is exactly what the ApplicationBarBehavior does behind the scenes: add or remove items when the IsVisible property of each item changes, and that is why we actually see this animation glitch.

Now presenting the MultiApplicationBarBehavior

Fixing this issue will require changing the whole application bar associated with the page, instead of just adding or removing buttons one by one.

And that is exactly what the MultiApplicationBarBehavior does: it allows you to have multiples application bar controls representing different states of the app bar!

Here’s the same app bar from the first article, now using the “multi” version:

<!-- remaining code -->

<Grid x:Name="LayoutRoot" Background="Transparent">
    <i:Interaction.Behaviors>
        <cimbalino:MultiApplicationBarBehavior SelectedIndex="{Binding ApplicationBarSelectedIndex}">
            <cimbalino:ApplicationBar>
                <cimbalino:ApplicationBarIconButton Command="{Binding AddItemCommand, Mode=OneTime}" IconUri="/Images/appbar.add.rest.png" Text="add" />
                <cimbalino:ApplicationBarIconButton Command="{Binding EnableSelectionCommand, Mode=OneTime}" IconUri="/Images/appbar.manage.rest.png" Text="select" />
            </cimbalino:ApplicationBar>
            <cimbalino:ApplicationBar>
                <cimbalino:ApplicationBarIconButton Command="{Binding DeleteItemsCommand, Mode=OneTime}" CommandParameter="{Binding SelectedItems, ElementName=ItemsMultiselectList}" IconUri="/Images/appbar.delete.rest.png" Text="delete" />
            </cimbalino:ApplicationBar>
        </cimbalino:MultiApplicationBarBehavior>
    </i:Interaction.Behaviors>

    <!-- remaining code -->

</Grid>

<!-- remaining code -->

Major difference here is the presence of multiple ApplicationBar entries, but also the MultiApplicationBarBehavior.SelectedIndex property which will allow you to select what app bar you want to show.

Here’s the recording of the app bar transition now:

MultiApplicationBarBehavior

Much nicer, but just to make sure, here is the same animation but about 5 times slower:

MultiApplicationBarBehavior (Slower)

Cimbalino Windows Phone Toolkit: ApplicationBarBehavior

Cimbalino Windows Phone ToolkitThe Windows Phone Application Bar has been a true headache for developers since day one, given that this object is not a FrameworkElement.

What this means is that we are unable to apply Styles or Templates to an ApplicationBar object, but most important, we are unable to bind to its properties, something that is a big issue when you what to use MVVM pattern in you apps.

Surely MVVM is not a closed pattern, and as such there are alternatives to overcome this issue (like this one or this one)!

In my case, in order to access the ApplicationBar in my apps in a more “MVVM’ed” way, I created the ApplicationBarBehavior that you can find in the Cimbalino Windows Phone Toolkit!

This Behavior, when applied to a PhoneApplicationPage or it’s LayoutRoot element, allows to create and maintain a fully bindable Application Bar, and as such applying a more consistent MVVM pattern.

Here’s a small sample code for it:

<!-- remaining code -->

<Grid x:Name="LayoutRoot" Background="Transparent">
    <i:Interaction.Behaviors>
        <cimbalino:ApplicationBarBehavior>
            <cimbalino:ApplicationBarIconButton Command="{Binding AddItemCommand, Mode=OneTime}" IconUri="/Images/appbar.add.rest.png" Text="add" IsVisible="{Binding IsSelectionDisabled}" />
            <cimbalino:ApplicationBarIconButton Command="{Binding EnableSelectionCommand, Mode=OneTime}" IconUri="/Images/appbar.manage.rest.png" Text="select" IsVisible="{Binding IsSelectionDisabled}" />
            <cimbalino:ApplicationBarIconButton Command="{Binding DeleteItemsCommand, Mode=OneTime}" CommandParameter="{Binding SelectedItems, ElementName=ItemsMultiselectList}" IconUri="/Images/appbar.delete.rest.png" Text="delete" IsVisible="{Binding IsSelectionEnabled}" />
        </cimbalino:ApplicationBarBehavior>
    </i:Interaction.Behaviors>

    <!-- remaining code -->

</Grid>

<!-- remaining code -->

In this small code sample we can see the ApplicationBarBehavior and in it, some ApplicationBarIconButton (like you would do in the current one), and quickly we notice some new properties like Command, CommandParamenter, and IsVisible (something we can’t even find in the base Windows Phone ApplicationBar); obviously, even the properties Text and IconUri are bindable, allowing for easy localization! ;)

Updated: Reduce the size of your XAP/APPX package!

In my previous post I wrote about an issue with the current build process for Windows 8 and Windows Phone 8 apps, where the Xml Documentation would get bundled in the output packages (APPX and XAP).

A few days later, I started to get some comments over the internet regarding the need to add my fix to all projects in a solution in order to make it fully work, something that turned out to be a bit tedious…

I have now updated the original post with a new solution that will only require you to change the projects that actually have a package output! :)

Please check the original post and update your projects to match the new change!

Reduce the size of your XAP/APPX package: time to take out the trash!

Updated on 20/02/2013

Before you even continue reading this article, I must just address a small warning: the following information has passed the WOMM certification, and as such, this works on my machine…

Works on my machine

Recently, while browsing StackOverflow as I normally do, I found a question that really caught my attention:

Visual Studio packs into WP8 XAP unnecessary XML doc files

If you create Windows Phone 8 App in Visual Studio and reference any libs with XML documentation files supplied from nuget or manually, Visual Studio will automatically pack those XML files into output XAP as well.

In our case this weird behavior of Visual Studio increases XAP size almost twice. (We have 8Mb of xml docs in total.)

There is no such problem for WP7 app projects.

After reading this, I had to confirm this behavior myself! Here’s what I did:

  • Created a blank solution
  • Added two Windows Phone projects, one with the 7.1 SDK and the other with the 8.0.
  • Used NuGet to add Json.net package to both projects
  • Build the solution

These are the XAP files resulting from building each project:

Windows Phone XAP files from both projects

As you can see here, the WP8 version is about 60Kb larger than the WP7 version. That’s 42% larger!!!

Here is the content of the WP7 XAP file:

Windows Phone 7 XAP contents

And this is the content of the WP8 XAP file:

Windows Phone 8 XAP contents

If you look closely on the WP8 version above, you’ll see a Newtonsoft.Json.xml file - that’s the Json.net Xml Documentation!

What is it doing there? Nothing. Can we safely remove it? Most definitely, yes!

My research on why this only happens in Windows Phone 8 lead to the MSBuild process, specifically the ResolveAssemblyReferences task on Microsoft.Common.targets file: this particular task returns a variable called ReferenceCopyLocalPaths, referring to “Paths to files that should be copied to the local directory.” which upon inspection, proved to have our “garbage files”!

To fix this, edit the *.csproj files for your projects that have package outputs (XAP or APPX), and add this to the end of the file, just before the </Project> closing tag:

<PropertyGroup>
  <FilesToXapDependsOn>$(FilesToXapDependsOn);BeforeFilesToXap</FilesToXapDependsOn>
</PropertyGroup>
<Target Name="BeforeFilesToXap">
  <ItemGroup>
    <FilteredPackagingOutputs Remove="@(FilteredPackagingOutputs)" Condition="'%(FilteredPackagingOutputs.OutputGroup)' == 'CopyLocalFilesOutputGroup' AND '%(FilteredPackagingOutputs.Extension)' == '.xml'"/>
  </ItemGroup>
</Target>

This custom target will run just before the FilesToXap target, telling MSBuild to remove all XML Documentation files from the list of files to copy.

So far this has proven to work perfectly for my applications, and when I applied it to my WP8 test project, I managed to get a much more reasonable 174KB XAP file!

One final note: although this article focus on Windows Phone, I actually found out that Windows Store Apps are also affected by this issue, and that the same solution can be used to fix the problem!

Error: Nuget.exe exited with code -1073741819

Lately I’ve been getting more and more this type of error from Nuget Package Restore when building my apps:

NuGet -1073741819 error

This seems to be a completely random issue with Nuget, as I see it happening with different projects, and sometimes not even happening at all!

Problem is that I work with some big/complex solutions that have a lot of projects, each one with it’s own packages.config file that can show this issue, so that sums up to a lot of failed builds!

There are actually a few open tickets about this in Codeplex, but given that this issue has been reported a while ago and so far it has not been solved, I thought on tackle this myself!

“If at first you don’t succeed, try and try again”

Following that motto, I thought on changing the Nuget Package Restore process so that it will retry a few times before aborting the build!

The easiest way I found to achieve this goal is just to change the .nuget\NuGet.targets file on the root of the solution. Inside this file, I found the following:

<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
    <Exec Command="$(RestoreCommand)"
          Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />

    <Exec Command="$(RestoreCommand)"
          LogStandardErrorAsError="true"
          Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
</Target>

Above you can see the MSBuild target that actually runs Nuget.exe, and so this is the one I will change to “fix” the issue.

This is my improved RestorePackages target:

<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites" Condition="Exists('$(PackagesConfig)')">
    <PropertyGroup>
        <NugetLogStandardErrorAsError Condition="'$(OS)' == 'Windows_NT'">true</NugetLogStandardErrorAsError>
        <NugetLogStandardErrorAsError Condition="'$(OS)' != 'Windows_NT'">false</NugetLogStandardErrorAsError>
    </PropertyGroup>

    <Exec Command="$(RestoreCommand)" LogStandardErrorAsError="$(NugetLogStandardErrorAsError)" IgnoreExitCode="True">
        <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
    </Exec>

    <Message Text="Error occurred, #1 retry..." Importance="High" Condition=" $(ExitCode) != 0 " />

    <Exec Command="$(RestoreCommand)" LogStandardErrorAsError="$(NugetLogStandardErrorAsError)" IgnoreExitCode="True" Condition=" $(ExitCode) != 0 ">
        <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
    </Exec>

    <Message Text="Error occurred, #2 and last retry..." Importance="High" Condition=" $(ExitCode) != 0 " />

    <Exec Command="$(RestoreCommand)" LogStandardErrorAsError="$(NugetLogStandardErrorAsError)" Condition=" $(ExitCode) != 0 " />
</Target>

You can see three consecutive Exec tasks here, each one will run depending on the previous one exit code, and only the last one will actually abort the build.

What this means is that if Nuget fails, we will retry it two more times before aborting the build!

As you can see, this is not a proper fix for the issue, it just bypasses it… so I’m still waiting for a fix on this - and I’m now looking at you, Nuget dev team! ;)

The FrameworkElement.Language property and why should you care!

The first time I came aware of this issue was when reading a post by Portuguese MVP Paulo Morgado on the App Hub Forums:

If all the emulator settings are set to “Portuguese (Portugal)” (both interface as all regional settings), how come when I use an IValueConverter on any Binding expression, the “culture” parameter has a “en-US” CultureInfo?…

To properly research on the subject, I created a small app with two TextBlock controls that show the Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture current values, and a third TextBlock with an IValueConverter that basically returns the culture.Name he is using, and the result was quite surprising!

Here is the code for my CultureDebugValueConverter class, implementing an IValueConverter:

public class CultureDebugValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return culture.Name;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Notice that no conversion is actually being made (the value parameter isn’t even being used), it just returns the “culture.Name” value from it.

Here’s the main ContentPanel on the MainPage.xaml:

<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <TextBlock Style="{StaticResource PhoneTextSubtleStyle}">CurrentCulture</TextBlock>
    <TextBlock Text="{Binding CurrentCulture}" Style="{StaticResource PhoneTextTitle2Style}" />
    <TextBlock Style="{StaticResource PhoneTextSubtleStyle}">CurrentUICulture</TextBlock>
    <TextBlock Text="{Binding CurrentUICulture}" Style="{StaticResource PhoneTextTitle2Style}" />
    <TextBlock Style="{StaticResource PhoneTextSubtleStyle}">Converter Culture</TextBlock>
    <TextBlock Text="{Binding Converter={StaticResource CultureDebugValueConverter}}" Style="{StaticResource PhoneTextTitle2Style}" />
</StackPanel>

As you can see, the last TextBlock just sets the Binding.Converter to a StaticResource of CultureDebugValueConverter type.

This is the remaining code placed on MainPage.xaml.cs:

public partial class MainPage : PhoneApplicationPage
{
    public MainPage()
    {
        InitializeComponent(); 

        this.DataContext = this;
    } 

    public string CurrentCulture
    {
        get
        {
            return Thread.CurrentThread.CurrentCulture.Name;
        }
    }

    public string CurrentUICulture
    {
        get
        {
            return Thread.CurrentThread.CurrentUICulture.Name;
        }
    }
}

Finally, I started the emulator, changed all the regional settings to “Portuguese (Portugal), and this is what I got after running the app:

LanguageTestApp original version

So the real question right now is: If the operating system interface, the CurrentCulture, and the CurrentUICulture are all set to “pt-PT”, from where did that “en-US” came from?

There is no trivial reason for this behavior, and to completely understand it, we first need to know how the “culture” parameter on IValueConverter.Convert method works; on the documentation, you can read the following: * The culture is determined in the following order:

  • The converter looks for the ConverterCulture property on the Binding object.
  • If the ConverterCulture value is null, the value of the Language property is used.

Given that I didn’t set the Binding.ConverterCulture property, this means it will fallback to the FrameworkElement.Language, which in turn has this in the docs:

The default is an XmlLanguage object that has its IetfLanguageTag value set to the string “en-US”**

We have finally found the “guilty” one!!!

Now that we know this, we can fix it just by setting the Page.Language property! The fixed code should look something like this:

public MainPage()
{
    Language = System.Windows.Markup.XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentUICulture.Name);

    InitializeComponent();

    this.DataContext = this;
}

If you look closely on the 3rd line, you’ll see the Language property set to a XmlLanguage instance created with the CurrentUICulture.Name.

Be aware that for this to work, you must set the Language property before the InitializeComponent method gets invoked!

And here’s the final result:

LanguageTestApp fixed version

I honestly don’t know the reason for this strange behavior, but this is a problem to account for if you have localization needs for your Windows Phone app!

The demo project I created and used for this article can be downloaded from here!

How to force a focused Textbox binding to update when I tap an app bar item

If you have TextBox controls in your app and you’re binding to the Text property (two-way mode), you should by now have noticed that the binding source isn’t updated when you tap an icon or menu item in the app bar!

The first thing you need to know in order to understand why this is happening, is that the TextBox control only updates the Text binding source when the control looses focus.

Second reason is that the ApplicationBar control can’t get focus, nor can it’s ApplicationBarIconButton or ApplicationBarMenuItem controls, so when you tap on them, the click event will be invoked without the TextBox control ever loosing focus!

To fix this behavior we need to force an update on the binding source when the click event get’s invoked, and here’s some code on how to achieve this:

var focusedElement = FocusManager.GetFocusedElement();
var focusedTextBox = focusedElement as TextBox;

if (focusedTextBox != null)
{
    var binding = focusedTextBox.GetBindingExpression(TextBox.TextProperty);

    if (binding != null)
    {
        binding.UpdateSource();
    }
}

We start by using FocusManager.GetFocusedElement method to get the current focused element. Then we check if that is a TextBox control, and if so, force it to update the Text property binding source!

The same problem will happen with PasswordBox, so it’s best just to handle both situations and encapsulate this in a reusable method:

public static void FocusedTextBoxUpdateSource()
{
    var focusedElement = FocusManager.GetFocusedElement();
    var focusedTextBox = focusedElement as TextBox;

    if (focusedTextBox != null)
    {
        var binding = focusedTextBox.GetBindingExpression(TextBox.TextProperty);

        if (binding != null)
        {
            binding.UpdateSource();
        }
    }
    else
    {
        var focusedPasswordBox = focusedElement as PasswordBox;

        if (focusedPasswordBox != null)
        {
            var binding = focusedPasswordBox.GetBindingExpression(PasswordBox.PasswordProperty);

            if (binding != null)
            {
                binding.UpdateSource();
            }
        }
    }
}

All you now need is to call the FocusedTextBoxUpdateSource method in the start of the app bar item control click event handler so that it will update the binding source before the rest of the code runs!

You can find this problem fixed on some toolkits and frameworks, like Caliburn.Micro and my own Cimbalino Windows Phone Toolkit ApplicationBarBehavior.

Another way to fix this would be by updating the binding source on text changed rather than when it looses focus, and for that you can use the TextBinding helper from Coding4Fun Toolkit for Windows Phone.

Windows Phone Choosers with async/await

Currently, Windows Phone Choosers work is by invoking the Show method and then subscribing the Completed event and waiting for it to be invoked.

Wouldn’t it be great to just use await chooser.ShowAsync() and get the results immediately?

All choosers extend the [ChooserBase](http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff707923(v=vs.105).aspx) class, and it's exactly for this class that we are going to use to create a ShowAsync extension method.

We start by creating the extension method signature:

public static class ExtensionMethods
{
    public static Task<TTaskEventArgs> ShowAsync<TTaskEventArgs>(this ChooserBase<TTaskEventArgs> chooser)
        where TTaskEventArgs : TaskEventArgs
    {
    }
}

The async methods are required to return void, Task, or Task in order to be invoked with the await keyword. So our method will return a Task value, where the TTaskEventArgs generic type must be a [TaskEventArgs](http://msdn.microsoft.com/en-US/library/windowsphone/develop/microsoft.phone.tasks.taskeventargs(v=vs.105).aspx) subtype.

We will need to use a TaskCompletionSource object so we can return a Task and later on set the result of the asynchronous operation.

var taskCompletionSource = new TaskCompletionSource<TTaskEventArgs>();

Next we will add the code for the normal Chooser handling:

EventHandler<TTaskEventArgs> completed = null;

completed = (s, e) => {
    chooser.Completed -= completed;

    taskCompletionSource.SetResult(e);
};

chooser.Completed += completed;
chooser.Show();

Notice that we are removing the event handler after it gets invoked as not to have a memory leak! All that is missing now is just returning the Task object:

return taskCompletionSource.Task;

And that’s it!

Here’s how the full extension method should look:

public static class ExtensionMethods {
    public static Task<TTaskEventArgs> ShowAsync<TTaskEventArgs>(this ChooserBase<TTaskEventArgs> chooser)
        where TTaskEventArgs : TaskEventArgs
    {
        var taskCompletionSource = new TaskCompletionSource<TTaskEventArgs>();

        EventHandler<TTaskEventArgs> completed = null;

        completed = (s, e) => {
            chooser.Completed -= completed;

            taskCompletionSource.SetResult(e);
        };

        chooser.Completed += completed;
        chooser.Show();

        return taskCompletionSource.Task;
    }
}

You can download a sample code for this directly from the Microsoft Code Gallery.