ILRepack – E Pluribus Unum: One assembly from many

Sometimes it is just much easier to deploy a single assembly that includes all dependencies.  ILRepack and ILRepack.MSBuild.Task will do just that for you.  Since I like to have Visual Studio and my build environment do this for me, I went with ILRepack.MSBuild.Task.

The Sample

In order to showcase packing an assembly into my program, first I need a program that has a dependency.  I decided to go with a simple console app that has a dependency on the Humanizer NuGet package to tell you how long you have to wait until your birthday. 

>Repack.exe
Usage:   repack [date]
  Prints how long it is until your birthday.
  If you don't supply your birthday, it uses mine.

23 weeks until your birthday

I created a new console project in Visual Studio and named it Repack.  I then included the Humanizer DLL using the NuGet package manager. 

You can find the source code on github.

Using ILRepack

All you need to do is add the following snippet at the end of your .csproj file.  To do this, you can open up the .csproj file in notepad or your favorite text editor.

<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

 <ItemGroup>
  <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
  <InputAssemblies Include="$(OutputPath)\*.dll" />
 </ItemGroup>

 <ILRepack 
  Parallel="true"
  Internalize="true"
  InputAssemblies="@(InputAssemblies)"
  TargetKind="EXE"
  OutputFile="$(OutputPath)\$(AssemblyName).exe"
 />
</Target>

Because we name the target “AfterBuild”, this code will automatically be run after msbuild or Visual Studio builds our project.  Setting the condition ensures that this will only run when we are in release mode.  You can definitely run this on debug builds, but it’s less likely that you’d want to.

The ItemGroup specifies lets us create a list of assemblies to include in the package.  The first assembly should be your assembly.  In my example it will be my executable file “Repack.exe”.  Next, I include all the DLLs in the output directory.  This way, if I add a new dependency later, it will be included automatically.

Note that the order does matter.  You will want to put the .exe first in this list.

Next all we need to do is call ILRepack.  You can specify the output file to be anywhere you like, but in this example I overwrite the existing Repack.exe with the packed version.

Once you rebuild your project (in release mode), you can copy the EXE anywhere you want and it will run. 

Summary

ILRepack.MSBuild.Task let’s you package DLL’s into your EXE file so you can copy just the executable anywhere and not have to worry about deploying the dependencies as well.

Full sample code can be found on github.

Happy coding.

Convert Azure Publish Profiles to FileZilla config files

Occasionally I need to FTP into one of my Azure websites.  Sometimes it’s to look at the logs; other times to upload a few files.  Just about every time I go to do this, I realize that I don’t know the credentials.  So I go and download the publish profile and open it up in my favorite text editor to get the FTP information and manually enter that in FileZilla.

I quickly became tired of doing this, so I wrote a console app that will do it for me.  The source code and executable are available on my GitHub.

Usage

  1. Download your publish profile
  2. Run the command line tool
  3. Import the config file to FileZilla

Download your publish profile

Log on to the Azure management portal for the website you want to FTP into.  On the right side of the dashboard page you will see an option to “Download the publish profile.”  Click it and you’re on your way.

amp

When downloaded the file will look something like this:

<?xml version="1.0" encoding="utf-8" ?>
<publishData>
  <publishProfile
    profileName="TestSite - Web Deploy"
    publishMethod="MSDeploy"
    publishUrl="testSite.scm.azurewebsites.net:443"
    msdeploySite="testSite"
    userName="$testSite"
    userPWD="test password"
    destinationAppUrl="http://testSite.azurewebsites.net"
    SQLServerDBConnectionString=""
    hostingProviderForumLink=""
    controlPanelLink="http://windows.azure.com"
    webSystem="WebSites">
  </publishProfile>
  <publishProfile
    profileName="TestSite - FTP"
    publishMethod="FTP"
    publishUrl="ftp://waws.ftp.azurewebsites.windows.net/site/wwwroot"
    ftpPassiveMode="True"
    userName="testSite\$testSite"
    userPWD="test password"
    destinationAppUrl="http://testSite.azurewebsites.net"
    SQLServerDBConnectionString=""
    hostingProviderForumLink=""
    controlPanelLink="http://windows.azure.com"
    webSystem="WebSites">
  </publishProfile>
</publishData>

Obviously, all the pertinent connection information has been scrubbed clean.  But you get the idea.

Run the command line tool

Next thing you need to do is run pubToFz.exe to convert the publish profile into a format that FileZilla understands.  Assuming the default download location, the command would look like this:

pubToFz %home%\downloads\testSite.publishProfile

By default, the tool creates an file named FileZilla.xml in the current directory.  The file will look something like this.

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<FileZilla3>
  <Servers>
    <Server>
      <Host>waws.ftp.azurewebsites.windows.net</Host>
      <Port>21</Port>
      <Protocol>0</Protocol>
      <Type>0</Type>
      <User>testsite\$testsite</User>
      <Pass encoding="base64">base 64 encoded test password</Pass>
      <Logontype>1</Logontype>
      <TimezoneOffset>0</TimezoneOffset>
      <PasvMode>MODE_DEFAULT</PasvMode>
      <MaximumMultipleConnections>0</MaximumMultipleConnections>
      <EncodingType>Auto</EncodingType>
      <BypassProxy>0</BypassProxy>
      <Name>TestSite</Name>
      <Comments />
      <LocalDir />
      <RemoteDir />
      <SyncBrowsing>0</SyncBrowsing>
    </Server>
  </Servers>
</FileZilla3>

Again, this was scrubbed clean.

Import the config file to FileZilla

Now all you have to do is open up FileZilla and import the config file that you just saved.

fzImport

Debugging a Visual Studio Crash

After a recent reboot, Visual Studio just stopped working.  Whenever I clicked on the icon on my desktop, I’d see this:

image

When the obvious solution (restarting my computer) I had to dig a little deeper.

Step 1:  Logs

The first step is to get some more information.  You can tell Visual Studio to log at startup by passing it the /log parameter on the command line.  Now, I’m fairly comfortable with the command line, but I rarely ever use it to start up Visual Studio.

An easier way is to just use the Diagnostic Mode option in the jump list.  Right click on the Visual Studio icon in your taskbar and select Diagnostic Mode.

image

Now all I had to do was wait for Visual Studio to crash again.  To get to the logs right click on the Visual Studio icon again select Open Activity Log Location.  With my setup, this opened C:\Users\Josh\AppData\Roaming\Microsoft\VisualStudio\12.0.  The log file is ActivityLog.xml.

In the log just search for a line like

<type>Error</type>

Hopefully, there aren’t too many of them.  In my case it pointed to a missing DLL

  <entry>
    <record>371</record>
    <time>2015/01/26 21:26:02.821</time>
    <type>Error</type>
    <source>Microsoft.VisualStudio.CommonIDE.ExtensibilityHosting.VsShellComponentModelHost</source>
    <description>Could not load file or assembly &apos;GettingStartedSetup.dll&apos; or one of its dependencies. The system cannot find the file specified.</description>
    <path>C:\USERS\JOSH\APPDATA\LOCAL\MICROSOFT\VISUALSTUDIO\12.0\EXTENSIONS\UVLFSVOS.E40\GettingStartedSetup.dll</path>
  </entry>

I went to the folder specified and verified that the DLL was missing.  Next thing to do is open up the extension.vsixmanifest to determine which extension it was.  Looking at the DisplayName node, it was fairly clear that it was Release Management tools for Visual Studio 2013.

<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
  <Metadata>
    <Identity Id="9b4bef8e-2ac3-4fa8-b8c7-d93d73d3618b" Version="2.2" Language="en-US" Publisher="Microsoft" />
    <DisplayName xml:space="preserve">Release Management tools for Visual Studio 2013</DisplayName>
    <Description xml:space="preserve">Release Management tools for Visual Studio helps to quickly get started with creating a Release Definition to automate the deployment of your application to multiple stages. You start with a working Build definition and then using this tool, set up a release pipeline that enables triggering of a Release for each build that is available for the build definition.</Description>
    <MoreInfo>http://www.visualstudio.com/products/release-management-for-microsoft-visual-studio-vs</MoreInfo>
    ...
  </Metadata>
    ...
</PackageManifest>

Step 2:  Safe Mode

Now that I know which extension was misbehaving, all I needed to do was uninstall it.

Open up Visual Studio in safe mode.  This can be done with a command line switch or through the jump menu again.

image

Visual Studio should open w/out a problem.  From here, it’s easy sailing.  Open up the Extensions and Updates tool, find the problematic extension in the Installed list, and press the uninstall button.

image

Now I was able to restart Visual Studio and it worked just fine.  I could have re-installed the extension, but I didn’t really need it so I just left it uninstalled.

Creating Drawables for Android

One of the pains for Android development for me is creating drawables in different sizes for various devices. In the past I’d only have a few images at a time to resize so I’d normally just upload them to Android Asset Studio and have the site generate the correct sizes for me.

There are two problems with this approach.  First, I have to upload the files one at a time.  If I have more than 4 files then it becomes a bit of a chore.  Second, I can’t specify what size I want the output.  It always  generates files that are

mdpi 32×32 pixels
hdpi 48×48 pixels
xhdpi 64×64 pixels
xxhdpi 96×96 pixels

Instead of manually editing the images I had (I had a lot) I decided to finally just write an app to handle this for me.  You can find it on GitHub at AndroidIconsResizer.  Right now it is a little barebones but it quickly and easily handles batches of images.

All options are optional so the simples use is to just run it.  If nothing is specified it assumes the current directory for all input or output.  By default the output images are all squares and are 100×100 at the mdpi size.

> AndroidIconResizer

It looks for all the .png files in current directory, resizes them and copies them to the appropriate output directories.  If you ran the above command in the following directory

.
..
file.png
anotherFile.png

then the directory would look like this after

.
..
file.png
res/
    drawable-mdpi/
        file.png (100 x 100 pixels)
        anotherFile.png (100 x 100 pixels)
    drawable-hdpi/
        file.png (150 x 150 pixels)
        anotherFile.png (150 x 150 pixels)
    drawable-xhdpi/
        file.png (200 x 200 pixels)
        anotherFile.png (200 x 200 pixels)
    drawable-xxhdpi/
        file.png (300 x 300 pixels)
        anotherFile.png (300 x 300 pixels)

It is possible to specify different sizes (heights and widths) for the output images.  All you need to specify is the size you want the mdpi image.  The other sizes are extrapolated based on Google’s iconography recommendations.

> AndroidIconResizer –w 20 –h 50

You can specify the input and output directories just as easily

> AndroidIconResizer –i inputDir –o outputDir

By default the xxxhdpi image isn’t generated since it’s only needed for launcher icons.  You can choose to include it with an option

> AndroidIconResizer –-include-xxxhdpi

Or you can just ask the tool itself for some help:

> AndroidIconResizer –help

Those were all the features I needed today, but I’ll probably be expanding on this app in the future.  Let me know if you’d want any other features.

Happy Coding.

Xamarin.Forms: Native Views

To recap, I’m writing a shopping cart app for Windows Phone, Android, and iOS.  The purpose of the app is primarily to let me use Forms.  Each post will build on top of the previous one.

Last time I fiddled with async loading and added an application level menu.  This week I’m going to add native views on Windows Phone and Android using PageRenders.

Recap and Code

This is the tenth post in the series, you can find the rest here:

  • Day 0:  Getting Started (blog / code)
  • Day 1:  Binding and Navigation (blog / code)
  • Day 2:  Frames, Event Handlers, and Binding Bugs (blog / code)
  • Day 3:  Images in Lists (blog / code)
  • Day 4:  Search and Barcode Scanner (blog / code)
  • Day 5:  Dependency Injection (blog / code)
  • Day 6:  Styling (blog / code)
  • Day 7:  Attached Behaviors (blog / code)
  • Day 8:  Writing to Disk (blog / code)
  • Day 9:  App and Action Bars (blog / code)
  • Day 10:  Native Views (blog / code)

For a full index of posts, including future posts, go to the GitHub project page.

About Page

I want to add a quick about page to the app.  I’ll be honest here, I couldn’t think of a great example where the views would be drastically different depending on the platform.  They will probably look almost exactly the same.  Specifically, they will contain two buttons that will take the user to this blog, (specifically this post), or to the GitHub project page.  The WinPhone version will contain two extra labels.  Not overly fancy, but educational enough.

First things first, I’ll add a simple view model:

public class AboutViewModel : BaseViewModel
{
    public AboutViewModel()
    {
        OpenUrlCommand = new Command<string>(s => Device.OpenUri(new Uri(s)));
    }

    public string BlogUrl { get { return @"http://blog.masterdevs.com/xf-day-10/"; } }

    public string CodeUrl { get { return @"https://github.com/jquintus/spikes/tree/master/XamarinSpikes/ShoppingCart"; } }

    public ICommand OpenUrlCommand { get; private set; }
}

 

The only thing remotely interesting here is the Device.OpenUri(…) call.  It does pretty much what you expect it to, namely opens the URI in the native browser.  This view model is so simple that I don’t even really need to inherit from BaseViewModel.  I do anyway just to future proof it and for consistency.

Next thing I need to do is add the AboutPage stub in in the core project (ShoppingCart.csproj).  For reasons I’ll go into a bit later, this can’t be defined in Xaml.

namespace ShoppingCart.Views
{
    public class AboutPage : ContentPage
    {
        public AboutPage()
        {
            Title = "About";
            Content = new Label { Text = "This page is not available for your platform", }; 
        }
    }
}

Nice and simple.  Just set the title and get out of there.

Now all I need to do is wire up a button somewhere to navigate me to this page.  I already have an action bar and app bar on the main CategoriesListPage, so I’ll just add another button there.

<ContentPage.ToolbarItems>
  <ToolbarItem Name="Log Out" Command="{Binding LogOut}"  Order="Primary" Priority="0">
    <ToolbarItem.Icon>
      <OnPlatform x:TypeArguments="FileImageSource"
                  WinPhone="Assets/Logout.png"
                  Android="ic_action_logout.png" />
    </ToolbarItem.Icon>
  </ToolbarItem>

  <ToolbarItem Name="About" 
               Command="{Binding AboutCommand}"  
               Order="Secondary" 
               Priority="0"/>
</ContentPage.ToolbarItems>

I don’t bother with an icon, so I put it in the “Secondary” order.  On WinPhone and Droid this means it will only show up win you hit the three dots to expand the menu.  It’s bound to the “AboutCommand” which just uses the existing navigation system to take you to the AboutPage.

WinPhone

The first step to getting a native page shown is to define a native page.  So here’s the Xaml for my WinPhoneAboutPage.

<phone:PhoneApplicationPage
    x:Class="ShoppingCart.WinPhone.Views.WinPhoneAboutPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d"
    shell:SystemTray.IsVisible="True">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="Shopping Cart"
                       Style="{StaticResource PhoneTextNormalStyle}"
                       Foreground="{StaticResource PhoneAccentBrush}" />
            <TextBlock Text="about" Margin="9,-7,0,0"
                       Style="{StaticResource PhoneTextTitle1Style}"
                       Foreground="{StaticResource PhoneAccentBrush}" />
        </StackPanel>

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Button Grid.Row="1" Content="Browse Source Code"
                    Command="{Binding OpenUrlCommand}"
                    CommandParameter="{Binding CodeUrl}" />

            <Button Grid.Row="3" Content="Read Blog"
                    Command="{Binding OpenUrlCommand}"
                    CommandParameter="{Binding BlogUrl}" />
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>

 

A very standard view.  The next thing I need to do is to set the DataContext of the page so my bindings actually work.  I’m inclined to follow the MvvmLight model with the ServiceLocator, but in all honesty that seems like a lot of ceremony for what I know will be one instance of a native view in this app.  So, I cheat a little a bit and just manually set the context in the code behind:

public partial class WinPhoneAboutPage : PhoneApplicationPage
{
    public WinPhoneAboutPage()
    {
        this.DataContext = ShoppingCart.App.AboutViewModel;
        InitializeComponent();
    }
}

Now to wire it up I’ll add a PageRenderer:

public class WinPhoneAboutPageRenderer :  Xamarin.Forms.Platform.WinPhone.PageRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
    {
        base.OnElementChanged(e);
        this.Children.Add(new AboutPage());
    }
}

And now that we have the PageRenderer defined, we need to tell the system to actually use it:

[assembly: ExportRenderer(typeof(ShoppingCart.Views.AboutPage), 
                          typeof(ShoppingCart.WinPhone.Views.WinPhoneAboutPageRenderer))]

 

This line can go anywhere in the assembly (just not within a namespace).  A lot of the examples place it in the same file as the renderer.  This has the benefit of keeping it close to where we’re using it.  I’ve elected to add this line at the beginning of the WinPhoneSetup file.  If we wind up with several definitions for renderers, it would be nice to have them all in one place.  I could be wrong about this.

Firing up the emulator and this looks… more than a little wrong.

WP Bad Renderer

So, on my fist pass of the ShoppingCart.AboutPage, I had added a label and two buttons.  When the WinPhoneAboutPageRenderer created the WinPhoneAboutPage, it just overlaid it on top of the existing controls.  Ok, so what if we add a call to Children.Clear()?  This still doesn’t look right, and to show exactly what’s wrong, I’ve added a splash of color to the page.

 

WP Bad Sizing

 

I set the background color of the entire page to red, and of the grid with my buttons to a light green.  As you can see, it’s not exactly taking up the entire page.

Children.Add doesn’t seem to be working for me at all, so I’ll try calling SetNativeControl.  The problem here is that since I’ve inherited from PageRenderer it expects a Xamarin.Forms.Page and I have a Microsoft.Phone.Controls.PhoneApplicationPage.  So I need to change what I’m inheriting from.

public class WinPhoneAboutPageRenderer 
  : VisualElementRenderer<Xamarin.Forms.Page, 
                          Microsoft.Phone.Controls.PhoneApplicationPage>
{
    protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
    {
        base.OnElementChanged(e);
        SetNativeControl(new WinPhoneAboutPage());
    }
}

 

Now that I’m inheriting from the VisualElementRenderer (the base class for the PageRenderer), I can specify that the object I’ll specify to replace the Xamarin.Forms.Page will be a WinPhone page.  Now it’s a simple matter of passing SetNativeControl a new instance of my WinPhoneAboutPage. This winds up looking like what I want.

WP Good

 

Droid About Page

Moving on to Droid, I create an xml file defining my layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <View
        android:layout_height="0dp"
        android:layout_width="fill_parent"
        android:layout_weight="1" />
    <Button
        android:id="@+id/button_blog"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Read Blog" />
    <View
        android:layout_height="0dp"
        android:layout_width="fill_parent"
        android:layout_weight="1" />
    <Button
        android:id="@+id/button_code"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Browse Code" />
    <View
        android:layout_height="0dp"
        android:layout_width="fill_parent"
        android:layout_weight="1" />
</LinearLayout>

Again, simple two buttons.  The views are just there as spacers.

And pretty much straight from the samples, here’s my renderer:

public class DroidAboutPageRenderer : PageRenderer
{
    private Android.Views.View _view;

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
    {
        base.OnElementChanged(e);

        AboutViewModel viewModel = App.AboutViewModel;
        var activity = this.Context as Activity;
        _view = activity.LayoutInflater.Inflate(Resource.Layout.AboutLayout, this, false);

        var blogButton = _view.FindViewById<Button>(Resource.Id.button_blog);
        var codeButton = _view.FindViewById<Button>(Resource.Id.button_code);

        blogButton.Click += (sender, ev) => viewModel.OpenUrlCommand.Execute(viewModel.BlogUrl);
        codeButton.Click += (sender, ev) => viewModel.OpenUrlCommand.Execute(viewModel.CodeUrl);
        AddView(_view);
    }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);
        var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
        var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
        _view.Measure(msw, msh);
        _view.Layout(0, 0, r - l, b - t);
    }
}

First things first, I grab the view model from my static cache.  Then I just inflate my view, and start grabbing my buttons so I can add click handlers.  Android doesn’t have a concept of data binding, so adding click handlers is a tad manual.  Once everything is wired up, I add my view to the renderer.  And now I have some errors.

I/MonoDroid( 1596): UNHANDLED EXCEPTION: System.InvalidOperationException: SetElement did not create the correct number of children
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.VisualElementPackager.SetElement (Xamarin.Forms.VisualElement oldElement, Xamarin.Forms.VisualElement newElement) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.VisualElementPackager.Load () [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[Xamarin.Forms.Page].SetPackager (Xamarin.Forms.Platform.Android.VisualElementPackager packager) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[Xamarin.Forms.Page].SetElement (Xamarin.Forms.Page element) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.VisualElementRenderer`1[Xamarin.Forms.Page].Xamarin.Forms.Platform.Android.IVisualElementRenderer.SetElement (Xamarin.Forms.VisualElement element) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.RendererFactory.GetRenderer (Xamarin.Forms.VisualElement view) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.NavigationRenderer.SwitchContentAsync (Xamarin.Forms.Page view, Boolean animated, Boolean removed) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.NavigationRenderer.OnPushAsync (Xamarin.Forms.Page view, Boolean animated) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.NavigationRenderer.PushViewAsync (Xamarin.Forms.Page page, Boolean animated) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.Platform.Android.NavigationRenderer.OnPushed (System.Object sender, Xamarin.Forms.NavigationRequestedEventArgs e) [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at Xamarin.Forms.NavigationPage+<PushAsync>d__c.MoveNext () [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596): --- End of stack trace from previous location where exception was thrown ---
I/MonoDroid( 1596):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at ShoppingCart.Services.AppNavigation+<ShowAbout>d__4.MoveNext () [0x0001e] in c:\code\Repos\spikes\XamarinSpikes\ShoppingCart\ShoppingCart\ShoppingCart\Services\AppNavigation.cs:35 
I/MonoDroid( 1596): --- End of stack trace from previous location where exception was thrown ---
I/MonoDroid( 1596):   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at System.Runtime.CompilerServices.TaskAwaiter.GetResult () [0x00000] in <filename unknown>:0 
I/MonoDroid( 1596):   at ShoppingCart.ViewModels.CategoriesListViewModel+ctor>b__2>d__a.MoveNext () [0x0001b] in c:\code\Repos\spikes\XamarinSpikes\ShoppingCart\ShoppingCart\ShoppingCart\ViewModels\CategoriesListViewModel.cs:39 

The stack trace doesn’t say it, but this error is raised when you call AddView if the ShoppingCart.AboutPage has already had the Content property set.  So, I go back to the AboutPage, and pull out the Content property:

namespace ShoppingCart.Views
{
    public class AboutPage : ContentPage
    {
        public AboutPage()
        {
            Title = "About";
        }
    }
}

Back to the DroidAboutPageRenderer, the OnLayout override is there to make sure that the view is sized to fit the whole screen.  From the top left (0, 0)  to the very bottom right (r-l, b-t)

Don’t forget to register it.  Again, I decided to add this to the top of DroidSetup.cs.

[assembly: ExportRenderer(typeof(ShoppingCart.Views.AboutPage), 
                          typeof(ShoppingCart.Droid.Renderers.DroidAboutPageRenderer))]

Running this up, we get a wonderful (if not pretty) native layout:

droid good

iOS About Page (A Default)

Don’t get too excited.  I still don’t have access to an iDevice.  But I wanted to at least try and make sure that the app wouldn’t crash on iOS.  I’ve updated the core definition of the AboutPage to at least show a label explaining that this page wasn’t available.

public class AboutPage : ContentPage
{
    public AboutPage()
    {
        Title = "About";

        if (Device.OS != TargetPlatform.Android)
        {
            Content = new Label
            {
                Text = "This page is not available for your platform",
            };
        }
    }
}

Since we saw that Android get’s really upset if you set the content in the core version of the page and then try to use a PageRenderer in the platform (at least with my implementation of the renderer), I make sure that we aren’t running on an Android device before setting the content.  The content could have been set to something much more complicated than just a simple label.  It could have even used data bindings like any other page.

Since I don’t have an iPhone, here’s what it looks like on a Droid.

droid unavailble

 

And now we have native views on 2 out of 3 platforms.

Happy Coding

Ready, set, action

I just had the need to style the search box in the actionbar of my Xamarin Android application. For those of you who don’t know, Xamarin lets you write native Android apps in .Net, specifically C#.

Here’s the search box before styling:

image

Here’s the look I was going for:

image

I was using ActionBarSherlock to create the actionbar.  After searching for a while, I came to the conclusion that the only way to customize the actionbar using the Android style system was to switch to AppCompat.  So now the steps seem pretty clear and easy:

  1. Migrate from ActionBarSherlock to AppCompat
  2. Create a style for my search box
  3. Apply style in just the right place.

I ran into more bumps along the way than expected, so I wanted to write down exactly what I had to do to get this working.

Migrating to from Sherlock to AppCompat

Before really considering using AppCompat, I checked to see how well it was supported by Xamarin and found a useful post on their blog with some sample code.  This looked promising and I was able to get it to compile locally, so full steam ahead.  Back in my project, I deleted the ActionBarSherlock Xamarin component and added in the AppCompat component.  I then walked through my code changing all code referencing Sherlock to AppCompat.  Wolram Rittmeyer has an excellent post on the step by step process to do this.

My first concern was that I also use MvvmCross, which requires that all Activity classes implement IMvxEventSourceActivity and IMvxAndroidView.  So months ago (almost a year ago according to my commit history) I created the  MvxActionBarSherlockFragmentActivity base class that inherits from SherlockFragmentActivity and implements the MvvmCross interfaces.  Not remembering what went into creating the class I was concerned it would be tedious to replace it with an AppCompat version.  Turns out it was trivial.  All I had to do was inhert from ActionBarActivity instead.  It was literally a one word change. Here’s my new MvxActionBarActivity:

using Android.App;
using Android.Content;
using Android.OS;
using Android.Support.V7.App;
using Cirrious.CrossCore.Core;
using Cirrious.CrossCore.Droid.Views;
using Cirrious.MvvmCross.Binding.BindingContext;
using Cirrious.MvvmCross.Binding.Droid.BindingContext;
using Cirrious.MvvmCross.Droid.Views;
using Cirrious.MvvmCross.ViewModels;
using System;

namespace Masterdevs.Droid.Views
{
    public class MvxActionBarActivity : ActionBarActivity, IMvxEventSourceActivity, IMvxAndroidView
    {
        protected MvxActionBarActivity()
        {
            BindingContext = new MvxAndroidBindingContext(this, this);
            this.AddEventListeners();
        }

        public event EventHandler<MvxValueEventArgs<MvxActivityResultParameters>> ActivityResultCalled;
        public event EventHandler<MvxValueEventArgs<Bundle>> CreateCalled;
        public event EventHandler<MvxValueEventArgs<Bundle>> CreateWillBeCalled;
        public event EventHandler DestroyCalled;
        public event EventHandler DisposeCalled;
        public event EventHandler<MvxValueEventArgs<Intent>> NewIntentCalled;
        public event EventHandler PauseCalled;
        public event EventHandler RestartCalled;
        public event EventHandler ResumeCalled;
        public event EventHandler<MvxValueEventArgs<Bundle>> SaveInstanceStateCalled;
        public event EventHandler<MvxValueEventArgs<MvxStartActivityForResultParameters>> StartActivityForResultCalled;
        public event EventHandler StartCalled;
        public event EventHandler StopCalled;

        public IMvxBindingContext BindingContext { get; set; }

        public object DataContext
        {
            get { return BindingContext.DataContext; }
            set { BindingContext.DataContext = value; }
        }

        public IMvxViewModel ViewModel
        {
            get { return DataContext as IMvxViewModel; }
            set
            {
                DataContext = value;
                OnViewModelSet();
            }
        }

        public void MvxInternalStartActivityForResult(Intent intent, int requestCode)
        {
            base.StartActivityForResult(intent, requestCode);
        }

        public override void SetContentView(int layoutResId)
        {
#if DEBUG // This try catch is super useful when debugging bad layouts.  No real need for it in prod.
            try
            {
#endif
                var view = this.BindingInflate(layoutResId, null);
                SetContentView(view);
#if DEBUG
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);  // Because of the JNI layers, this is the easiest way to reliably get the message from the exception when debugging.  The watch window isn't as reliable/timely
                throw;
            }
#endif
        }

        public override void StartActivityForResult(Intent intent, int requestCode)
        {
            StartActivityForResultCalled.Raise(this, new MvxStartActivityForResultParameters(intent, requestCode));
            base.StartActivityForResult(intent, requestCode);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                DisposeCalled.Raise(this);
            }
            base.Dispose(disposing);
        }

        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            ActivityResultCalled.Raise(this, new MvxActivityResultParameters(requestCode, resultCode, data));
            base.OnActivityResult(requestCode, resultCode, data);
        }

        protected override void OnCreate(Bundle bundle)
        {
            CreateWillBeCalled.Raise(this, bundle);
            base.OnCreate(bundle);
            CreateCalled.Raise(this, bundle);
        }

        protected override void OnDestroy()
        {
            DestroyCalled.Raise(this);
            base.OnDestroy();
        }

        protected override void OnNewIntent(Intent intent)
        {
            base.OnNewIntent(intent);
            NewIntentCalled.Raise(this, intent);
        }

        protected override void OnPause()
        {
            PauseCalled.Raise(this);
            base.OnPause();
        }

        protected override void OnRestart()
        {
            base.OnRestart();
            RestartCalled.Raise(this);
        }

        protected override void OnResume()
        {
            base.OnResume();
            ResumeCalled.Raise(this);
        }

        protected override void OnSaveInstanceState(Bundle outState)
        {
            SaveInstanceStateCalled.Raise(this, outState);
            base.OnSaveInstanceState(outState);
        }

        protected override void OnStart()
        {
            base.OnStart();
            StartCalled.Raise(this);
        }

        protected override void OnStop()
        {
            StopCalled.Raise(this);
            base.OnStop();
        }

        protected virtual void OnViewModelSet()
        {
        }
    }
}

With that done, all my MvvmCross worries were over and my app should compile.  Not quite.  On either score.  It turns out that the version of MvvmCross I was using was referencing the old Mono.Android.Support.v4.dll while the AppCompat library referenced the new Xamarin.Android.Support.v4.dll.  These are essentially the same library, but with different names.  There is an excellent summary on Xamarin’s bugzilla.  Finally after carefully reading through all of the bug report, at the very bottom, I found Stuart’s comment saying that he’d already released a fixed version.  All I had to do was update to the latest version of MvvmCross in NuGet.  And now my code actually compiled and my MvvmCross concerns were over.

Fixing the Null SearchView

While my code happily compiled, it wasn’t quite as happy about actually running.

public override bool OnCreateOptionsMenu(IMenu menu)
{
    MenuInflater.Inflate(Resource.Menu.ManageUsers, menu);
    var searchItem = menu.FindItem(Resource.Id.action_search);

    var view = MenuItemCompat.GetActionView(searchItem);
    var searchView = view.JavaCast<Android.Support.V7.Widget.SearchView>();

    searchView.QueryTextChange += (s, e) => ViewModel.Filter = e.NewText;

    return base.OnCreateOptionsMenu(menu);
}

Whenever I tried to get the action view from the search menu item, it was null.   My first instinct was to double check my menu definition:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto" >
  <item android:id="@+id/action_search"
        android:title="Search Friends"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="ifRoom|collapseActionView"
        app:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

It looked right.  I had remembered to use the AppCompat search view.  After some digging on the inter-tubes, I found a post on StackOverflow explaining that my themes had to specifically derive from AppCompat themes.  Ok, so a trip to the style generator and I’m using the correct themes.

Styling Search

So now it’s been a while, and I have a lot of checked out code.  But I’ve finally gotten back to where I was when I started.  An app that compiles, runs, and has an ugly search box.

The trick, (thanks to Andreas Nilsson for explaining it) is to set your own style  searchViewAutoCompleteTextView in the Theme.AppCompat style.

<resources>
    <style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
        <item name="android:actionBarWidgetTheme">@style/ActionBarWidget.actionbar</item>
    </style>

    <style name="ActionBarWidget.actionbar" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="searchViewAutoCompleteTextView">@style/AutoCompleteTextView.actionbar</item>
    </style>

    <style name="AutoCompleteTextView.actionbar" parent="Widget.AppCompat.Light.AutoCompleteTextView">
        <item name="android:textColor">#FFFFFF</item>
        <item name="android:textCursorDrawable">@null</item>
    </style>
</resources>

Thanks and Resources

Thanks to Wolfram Rittmeyer for his methodical description on how to migrate from Sherlock to AppCompat.  Another thanks to Andreas Nilsson for his blog post showing that it was even possible to customize the the search box using styles.  I encourage you to read both blog posts, since they go into far greater detail.

Happy Coding.

INotifyPropertyChanged – Hardcode This

Background

One thing I always hated about INotifyPropertyChanged is that when it was first introduced, the only way to actually notify a property is by specifying a hard coded value. I call this pattern, The Verbose. It looked something like this:

private int _Integer;
public int Integer
{
    get { return _Integer; }
    set
    {
        if (value != _Integer)
        {
            _Integer = value;
            Notify(@"Integer"); 
        }
    }
}

(Note: Notify is just a helper method to call PropertyChanged(this, new PropertyChangedEventArgs(propertyName));)

The thing that bothered me with this is that pesky Notify(@”Integer”). If you ever refactor that property, you’ll no longer be notified when Integer has been changed unless you go in and manually change the string. There has to be a better way.

After browsing some of the code from this project http://winrtclipboard.codeplex.com/, I found a really neat solution. They kept a Dictionary<string, object> that held all of the property values. This removed the need for the backing property (in this case _Integer). Then they used an Expression Class to pass a lambda in and get the property name. As a result, I dubbed this approach, The Expression and its definition looked like this:

public int Integer
{
    get { return GetValue(() => Integer); }
    set { SetValue(value, () => Integer); }
}

Now you can refactor all you want without ever breaking your notifications because the property name is coming from the Expression you pass into GetValue / SetValue. The one caveat to this implementation is performance. On every call to GetValue or SetValue you’re using reflection to get the member name. So depending on your particular scenario this can either be perfectly fine or a total deal breaker.

For a time, this was all we had . . . and then .NET 4.5 came along and we now have CallerMemberNameAttribute. It’s part of the new Complier Services that ship with VS 2012. The documentation indicates that INotifyPropertyChanged is a intended use for this attribute and they’re right. So if we leverage the Dictionary approach to holding our backing values, we can write properties that look like this:

public int Integer
{
    get { return GetValue<int>(); }
    set { SetValue(value); }
}

I dubbed this approach The Caller. Now that looks very clean. GetValue actually takes an optional parameter with the CallerMemberNameAttribute attached to it. So when we call it without any parameters, the compiler adds the parameter for us and in this case sets it to “Integer”. As it turns out this is faster then the Expression Class method, but using the Dictionary and constantly doing look ups still gives us a performance hit. With the use of a backing object and a helper method though, we can write clean code that performs well and refactors without issue. The result is The Caller Fast and a property definition that looks like this:

private int _Integer;
public int Integer
{
    get { return _Integer; }
    set { SetValue(ref _Integer, value); }
}

SetValue in this case simply compares _Integer & value. If they’re different, _Integer is set to value and Notify is called. Thanks to to CallerMemberNameAttribute we don’t have to pass in what property name just changed.

Performance

After discovering this wonderful attribute, I decided to create a little project that vetted the performance of several of these approaches. I’ve created a little solution that you can download to get all of the source code.

The test consisted of creating several objects, each implemented INotifyPropertyChanged in its own way. The objects are:

  • The Verbose – The initial method I showed. Classic INotifyPropertyChanged.
  • The Expression – The method from WinRTClipboard.CodePlex.com.
  • The Caller – Used CallerMemberAttribute with the dictionary from The Expression.
  • The Caller Fast – A modified version from MSDN to keep our property definitions looking nice and clean.

Each implementation implemented an interface that has 1 property, Integer. I created an array of 100,000 random integers. I then looped over this array for each object and set and get the value of Integer. I wrapped the entire loop in a stopwatch and wrote the results to the console. The results are as follows:

00:00:00.0040000 – The Verbose
00:00:00.0070000 – The Caller Fast
00:00:00.0280000 – The Caller
00:00:00.3070000 – The Expression

As you can see, The Verbose is the fastest. This makes sense as it’s the simplest implementation. The Caller Fast though is a very close second (Remember this a difference of 3 milliseconds for 100000 iterations). When you use a dictionary however, you loose an order of magnitude. The Expression, which uses both reflection and a dictionary to store values is 2 orders of magnitude slower then The Verbose.

Summary

In conclusion, if you can use .NET 4.5 you should really take advantage of CallerMemberNameAttribute. It performs very well and you can refactor your code without worrying about updating literals littered in your code. If you can’t upgrade to .NET 4.5, the Expression method is a very clean solution but shouldn’t be used in situations where you’ll be doing a lot of updates to your properties (i.e. animations).

I hope you found this useful and would love to hear your feedback, so leave us a comment.

Cheers!

//– Joe