comments edit

Following up on CoolWhip, ChocolateyCoolWhip is a nuget package that makes creating, packaging, and deploying your code through Chocolatey.org simple. Like CoolWhip, all you need to do to publish a new release is create release in GitHub.

Chocolatey?

In case you aren’t familiar, Chocolatey is a package manager for Windows built on top of NuGet and PowerShell. It allows users to download and install thousands of software programs with a single command. For example, to install nodejs, all you would need to do is open up a command prompt and enter

> choco install nodejs.install

Getting Started with ChocolateyCoolWhip

To get started, install the nuget package into your project. The first thing you’ll notice is that it creates nuspec and AppVeyor configuration files. Chocolatey uses the nuspec as metadata for your package, the same way NuGet does.

Once setup, all you need to do to update your package on Chocolatey.org is create a release in GitHub. ChocolateyCoolWhip will pull the version information directly from the release name and kick off a build in AppVeryor. You have complete control over versioning your application

Configuration is simple:

  1. Connect AppVeyor to your GitHub repo
  2. Install the NuGet package >Install-Package ChocolateyCoolWhip
  3. Update the generated nuspec file with your project’s information
  4. Add your authorization tokens to the AppVeyor.yml file
  5. Save/commit your changes

Once this is set up, all you’ll need to do in order to release (or update) your package on NuGet is create a GitHub release with the version number.

There is full step by step documentation in the wiki.

Happy Coding.

this post was originally on the MasterDevs Blog

comments edit

CoolWhip is a NuGet package aimed at making and deploying other NuGet packages easier. With CoolWhip, creating a Release in GitHub automatically pushes that release to NuGet.

Once you’ve installed CoolWhip into your project it will create a nuspec file and AppVeyor configuration file. These will work together to package your project and automatically upload it to NuGet.org.

Once setup, all you need to do to update your package on NuGet.org is create a release in GitHub. CoolWhip will pull the version information directly from the release name and kick off a build in AppVeryor. You have complete control over versioning your application.

To configure CoolWhip you need to

  1. Connect AppVeyor to your GitHub repo
  2. Install the NuGet package >Install-Package CoolWhip
  3. Update the generated nuspec file with your project’s information
  4. Add your authorization tokens to the AppVeyor.yml file
  5. Save/commit your changes

Once this is set up, all you’ll need to do in order to release (or update) your package on NuGet is create a GitHub release with the version number.

There is full step by step documentation in the wiki.

Happy Coding.

this post was originally on the MasterDevs Blog

comments edit

I’m OCD when it comes to my code. I don’t like to have any warnings. I wanted to configure my TeamCity builds to fail if there were any warnings in the projects. My first option is to tick the “Treat warnings as errors” box in the project settings. This had a few problems

Problem 1.

I’d have to remember to do it for every project in my repo, including all the projects I make in the future. Even worse, everyone on my team would have to remember to do that too. That’s not something I could rely on.

Problem 2.

While warnings are just errors that you’re ignoring, I will admit that it is convenient to be able to ignore some things some times. I’m fine with debugging and running locally with some errors. I really only wanted to stop people from committing code back to master with warnings. I couldn’t care less about bad hygiene the have when working locally.

The Solution

In searching, I found David Gardiner’s blog post in which he creates a power shell script to edit the xml in each csproj file. It looks simple enough so I removed the TFS bit and added it as a build step in my TeamCity flow. It runs right before compiling my code.

Get-ChildItem -Recurse -Filter "*.*csproj" | % {
    Write-Host $_.Name
     
    $filename = $_.Fullname
     
    $proj =
1
( Get-Content $_.Fullname ) $xmlNameSpace = new-object System.Xml.XmlNamespaceManager($proj.NameTable) $xmlNameSpace.AddNamespace("p", "http://schemas.microsoft.com/developer/msbuild/2003") $nodes = $proj.SelectNodes("/p:Project/p:PropertyGroup[@Condition and not (p:TreatWarningsAsErrors)]", $xmlNameSpace) $touched = $false $nodes | ForEach-Object -Process { $e = $proj.CreateElement("TreatWarningsAsErrors", "http://schemas.microsoft.com/developer/msbuild/2003") $e.set_InnerText("true") $_.AppendChild($e) | Out-Null $touched = $true } if ($touched) { Write-Host "Checkout $filename" $proj.Save("$($filename)") | Out-Null } }

this post was originally on the MasterDevs Blog

.NET, c# comments edit

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])(http://www.vim.org).

<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.

this post was originally on the MasterDevs Blog

c#, Tools comments edit

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.

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.

this post was originally on the MasterDevs Blog

comments edit

— layout: post disqus_identifier: #43 comments: true categories: [ cmd, tips ] — I recently stumbled across DOSKEY while reading StackOverflow. Reading the documentation I stumbled across something old and something new.

>doskey/?

<edit>
F7    Displays command history
F8    Searches command history

I knew about F7 and use it constantly when I’m on the command line. It pops up a scrollable list of your recent commands.

F8 lets you cycle through commands in your history with a search term.

Suppose you had previously typed a complex command. In the example I have below, I used the command echo Foxtrot Golf. To find and execute it again all you need to do is type the beginning of the command and then press the F8 key. In the example, I type echo on the command prompt and cycle through all the commands that start with that by pressing F8. To narrow it down a bit more, I type in echo F and then press F8 to get all the commands that start with that. Note that it is case sensitive.

this post was originally on the MasterDevs Blog

In Android, your options are kind of small for setting a font purely in XML.

In this post, I’ll create a converter so we can specify the font in an MvvmCross binding.

Getting a font

Before going any further, you need to actually get and include a font in your android app. For this example I will be using Fontin. The main reason I’m using it is because it was easy to find and is free. Download the TTF versions and and include them in your project. Add a new subdirectory to the Assets folder in your android project named “font”. Drop the files into that folder and include them in your project. Make sure that the build action is set to AndroidAsset.

If you get the following error, make sure that the font names are spelled exactly the same as the folder and file names, including capitalization.

java.lang.RuntimeException: native typeface cannot be made

In the example from my screenshots, my font name should be: font/Fontin-Italic.ttf.

And again, capitalization matters.

Binding to Typeface

The first step is to use MvvmCross. Next all you really need to do is bind directly to the Typeface property on the TextView. They Typeface property is an instance of of Typeface (nothing surprising there) which meanst that you’ll need a converter.

<TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      local:MvxBind="Text Hello; Typeface StringToFont(FontName)" />

The converter is pretty straight forward:

public class StringToFontConverter : MvxValueConverter<string, Typeface>
{
    private static Dictionary<string, Typeface> _cache = new Dictionary<string, Typeface>();
 
    protected override Typeface Convert(string fontName, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        try
        {
            if (!fontName.StartsWith(@"font/")) fontName = @"font/" + fontName;
            if (!fontName.EndsWith(".ttf")) fontName += ".ttf";
 
            if (!_cache.ContainsKey(fontName))
            {
                _cache[fontName] = Typeface.CreateFromAsset(Application.Context.Assets, fontName);
            }
 
            return _cache[fontName];
        }
        catch (Exception e)
        {
            Android.Util.Log.Error("AndroidFont", e.ToString());
 
            return Typeface.Default;
        }
    }
}

First thing the converter does is to clean the input, ensuring that the font name starts with the directory and ends with the ttf extension. This makes the binding a bit easier in that we don’t have to remember to get the full font path correct.

It then check its static cache to see if it already has an instance of the the font, if not it creates one by calling Typeface.CreateFromAsset. If creation fails it does some logging and return the default typeface. This is important because in my testing VisualStudio hang pretty hard under some circumstances where errors were ignored.

Fire this up, and you’ll see that the font is in fact set.

One problem with this example is that we are forcing the ViewModel to know the correct name for the font. In some cases that’s ok, in others, we won’t want to handle font in the VM layer. Luckily we can use Tibet binding and just bind to a static string in the xml. Just remember to surround it with single quotes.

<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    local:MvxBind="Text Hello; 
                   Typeface StringToFont('Fontin-Bold')" />

Sample

Here’s a sample layout putting everything together.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:textSize="40dp"
        local:MvxBind="Text Hello; Typeface StringToFont('Fontin-Bold')" />
 
<!-- Binding to the View Model -->
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="16dp"
        android:text="Bind to Typeface:  " />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="24dp"
        android:textSize="24dp"
        local:MvxBind="Text Hello; Typeface StringToFont(SelectedFont)" />
    <MvxSpinner
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:textSize="24dp"
        local:MvxBind="SelectedItem SelectedFont; ItemsSource FontNames;" />
 
<!-- Binding to a constant -->
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="16dp"
        android:text="Constant Typeface:  " />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="24dp"
        android:layout_marginBottom="24dp"
        android:textSize="24dp"
        local:MvxBind="Text Hello; Typeface StringToFont('Fontin-Bold')" />
 
<!-- Error -->
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="16dp"
        android:text="Error Handling:  " />
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="24dp"
        android:layout_marginBottom="24dp"
        android:textSize="24dp"
        local:MvxBind="Text Hello; Typeface StringToFont('Not a font name')" />
</LinearLayout>

The edit box and first text box are bound to the value in the spinner. The second text box is staticly bound to the bold font. The last text box is bound to a value that is not a valid font and defaults to the default Android font.

Here’s a link to the working project on git.

Happy Coding

this post was originally on the MasterDevs Blog

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.

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.

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.

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:

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.

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

Happy Coding

this post was originally on the MasterDevs Blog

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 wrote data to disk. This week I’m going to add an application level menu.

Reminder, this article is a direct continuation of last week’s article. The code base is entirely the same. The posts were split up so that neither would be too long. For consistency’s sake, I have created separate releases for each week.

Recap and Code

This is the ninth 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.

Logging Out

Now that I’m all logged in, I need to be able to log out. Ideally this would go in a dedicated page with various settings. But honestly, that’d be boring. This app already has plenty of pages. What it doesn’t have is a system level menu — an Action Bar on Droid or an App Bar on Windows Phone.

Adding the menu is rather straight forward, just some simple XAML and bindings to CategoriesListPage.xaml:

<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>
</ContentPage.ToolbarItems>

Conveniently, ToolbarItem has a Command property that you can bind against to handle clicks. The command binds the same as a button. The icon is a bit more involved.

Now the question is: where can I get good icons for my app? This leads me to a quick aside…

Windows Phone Icons

The easiest way to get icons for a Windows Phone or Metro-style Windows apps is to use Metro Studio by Syncfusion. First off, it’s free. Second off, it’s full of great icons. Just search for whatever you want, and then customize it for your uses. You can even create icons out of text in whatever font you like. Finally, a use for Wingdings.

Android Icons

Metro Studio packs a lot of punch, but doesn’t offer any help for Android apps (kinda makes sense given the name). For Android assets, check out the Android Asset Studio. There’s a lot of good stuff in here, but for this project I went straight to the Action Bar and Tab Icons section. They provide a library of images (although significantly smaller than Metro Studio), the ability to upload an image of your choice, or to enter an arbitrary string (and we still get Wingdings!). The best part is that it generates a zip with assets for various screen resolutions. Just unzip and drop the folders into the Resources directory.

Image Asset Locations

<ToolbarItem.Icon>
  <OnPlatform x:TypeArguments="FileImageSource"
              WinPhone="Assets/Logout.png"
              Android="ic_action_logout.png" />
</ToolbarItem.Icon>

Because I’m specifying the location of the icon as a string, I need to make sure that the images are placed in the correct locations in the corresponding project folders. The XF documentation explains pretty clearly where each goes.

For my WinPhone project, I place the Logout.png in the “Assets” folder.

Android is a little bit more complicated since the platform allows you to serve different sized images for devices with different resolutions. Each file is put in the corresponding drawable folder under “Resources”. As I said earlier, the Android Asset Studio does all this for you. You can just drop the folders it generates directly into the Resources folder.

Doing Async Work at Startup

Previously, when the app started up it went directly to the login screen. Now it has to first check to see if the user is logged in. If they are then the app goes to the categories page, otherwise it goes to the login page. This is easy, except for the fact that the check happens on the background thread and takes some time since it is going to disk. Not a lot of time, but enough that we aren’t guaranteed to get the result back before the app is ready to start up. In order to accommodate this, I’m turning the “WelcomePage” into a splash page. It will display a progress dialog for a little bit and then navigate to the next page once it knows which page that is. Let’s start with the view:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ShoppingCart.Views.WelcomePage"
             xmlns:local="clr-namespace:ShoppingCart;assembly=ShoppingCart"
             BindingContext="{x:Static local:App.WelcomeViewModel}"
             BackgroundColor="White">
 
  <StackLayout VerticalOptions="Center"
               IsVisible="{Binding IsLoaded, Mode=OneWayToSource}">
    <Frame>
      <Label Text="Welcome to The Store"
             Font="Bold, Large"
             HorizontalOptions="Center"
             TextColor="{x:Static local:App.AccentColor}" />
    </Frame>
 
    <ActivityIndicator IsRunning="{Binding IsBusy.IsNotCompleted}"
                       HorizontalOptions="FillAndExpand"
                       VerticalOptions="FillAndExpand"
                       Color="{x:Static local:App.AccentColor}" />
  </StackLayout>
</ContentPage>

The ActivityIndicator starting on line 18 is pretty straight forward. I bind whether or not it is running to the NotifyTaskCompletion property on the view model (more on that later), and the color to the static representation of the accent color in the same way that I do for the label. You should remember this from the styling article from a couple of weeks ago.

A little more interesting is the one way to source binding on the visibility of the stack layout. This is here to tell the view model that the view has been displayed. Since this is the first page in the XF app it is wrapped in the NavigationPage, which initializes the NavigationService. If we try to navigate away from this view before it is shown, we have no navigation service, and so navigation won’t work. Classic Catch-22.

public class WelcomeViewModel : BaseViewModel
{
    private readonly IAppNavigation _navi;
    private SemaphoreSlim _slim;
 
    public WelcomeViewModel(IAppNavigation navi)
    {
        _navi = navi;
        _slim = new SemaphoreSlim(0, 1);
        IsBusy = new NotifyTaskCompletion<int>(GoToFirstPage());
    }
 
    public NotifyTaskCompletion<int> IsBusy { get; private set; }
 
    public bool IsLoaded
    {
        get { return GetValue<bool>(); }
        set
        {
            SetValue(value);
            if (value)
            {
                _slim.Release();
            }
        }
    }
 
    private async Task<int> GoToFirstPage()
    {
        await _slim.WaitAsync();
        await _navi.SecondPage();
        return 0;
    }
}

The first thing the view model does is initialize a SemaphoreSlim in the unsignaled state, i.e., calling Wait() will block. It then creates a NotifyTaskCompletion of type int. Creating this kicks off the async call to GoToFirstPage. The return value doesn’t matter in this case, the object is just being used to run a background task and update the UI with the status.

When IsLoaded is set to true by the binding to the visibility of the StackLayout in the view, it signals the semaphore, allowing the WaitAsync in GoToFirstPage to complete. GoToFirstPage then tells the navigation service to show the second page in the app. The navigation service handles the logic of determining which page to show as well as actually navigating to the page. For the sake of demonstration, I’ve added a delay in the video below.

Here’s what the app looks like when the user needs to log in

And here’s what the returning a user sees

Happy Coding

this post was originally on the MasterDevs Blog

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 added behaviors to my XF xaml. This week I’m going to save settings to disk using Akavache.

Once I started writing the post to go along with this week’s post, I quickly became aware that the it was longer than what really makes sense for a single post. So I’m splitting the article in two. This week will be logging in, next week will be logging out. Both weeks will use the same code. For consistency’s sake, I’ll be creating a new release for next week, even though it will point to the same code.

Recap and Code This is the eight 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.

Installing Akavache Cheat Sheet

At the risk of spoiling the narrative below, here’s a very brief outline of the steps to install and use Akavache in a Xamarin Forms app. For links and more details, continue reading.

  1. Install Akavache package in common PCL project (Install-Package akavache)
  2. Install Akavache package in platform specific projects
    1. Droid
    2. Win Phone
    3. iOS (The iOS step is assumed to be necessary and sufficient to make Akavache work, but I am unable to verify it)
  3. WinPhone: Update Splat package (Update-Package splat)
  4. WinPhone: Change build configuration to x86

Logging In

From the beginning one of the things that really bothered me about this app is that I have to log in each time I use it. And that’s including the fact that I don’t have to type in a particular username/password. Any text will do. I guess I’m just lazy.

To persist logging in, I’m just going to write a little bit of information to disk when I’m logging in for the first time. Next time I open the app, I’ll just check for that value, if it exists I’ll go straight to the main landing page.

I don’t want to tie my implementation down to an unknown framework, so the first thing I need to do is create an interface to abstract away persisting data:

public interface ICache
{
    Task<T> GetObject<T>(string key);
    Task InsertObject<T>(string key, T value);
    Task RemoveObject(string key);
}

This interface should handle all of my CRUD operations. Right now the only person that needs to use it is my LoginService.

public async Task<User> LoginAsync(string username, string password)
{
    User user = Login(username, password);
 
    await _cache.InsertObject("LOGIN", user);
 
    return user;
}
 
public async Task<bool> IsLoggedIn()
{
    User user = await _cache.GetObject<User>("LOGIN");
    return user != null;
}

LoginAsync performs the standard log in check, verifying that username and password are valid credentials (in reality it just checks that they are non-null) and returns a user object if they are valid. I then save that in the cache using “LOGIN” as the key. Next, IsLoggedIn in checks to see if there is a non-null value stored in the cache.

Now that we know how the cache is going to be used, let’s implement it.

Akavache

I’ll be using Akavache as my data store. It’s probably a bit overkill for the very simple use case I have but I have a few reasons why I want to use it. First, I really don’t want to think about where exactly I’m storing this data. It could be in a database, it could be on disk, my app doesn’t really care. It’s just a set of keys and values to me. While Akavache does use a SQLite backend, I don’t have to know any of the details. I’m also looking for something that is async/await friendly. Akavache supports many platforms, I’d love to be able to write this once for all platforms. And finally, I recently heard about it and kind of wanted to play with it.

Here’s a summary of what I just stated above as my reasons for using Akavache

  • Abstract away storage details
  • async API
  • Cross platform
  • It’s new to me

Akavache on Droid

Akavache is a nuget package, so installation is easy. I’m installing the package into the core project (ShoppingCart.csproj). For it to work it also needs to be installed on the Droid project as well. In my Services folder I’ll add my Akavache implementation of ICache. This class will be used by all of the platforms.

using Akavache;
using ShoppingCart.Services;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading.Tasks;
 
namespace ShoppingCart.Services
{
    public class Cache : ICache
    {
        public Cache()
        {
            BlobCache.ApplicationName = "ShoppingCart";
        }
 
        public async Task RemoveObject(string key)
        {
            await BlobCache.LocalMachine.Invalidate(key);
        }
 
        public async Task<T> GetObject<T>(string key)
        {
            try
            {
                return await BlobCache.LocalMachine.GetObject<T>(key);
            }
            catch (KeyNotFoundException)
            {
                return default(T);
            }
        }
 
        public async Task InsertObject<T>(string key, T value)
        {
            await BlobCache.LocalMachine.InsertObject(key, value);
        }
    }
}

First thing to note here is that I’m importing the System.Reactive.Linq namespace. This enables us to await the Akavache calls. Next thing to note is that I’m setting the ApplicationName property in the constructor. This is needed to initialize storage. The rest of the implementation is pretty straight forward. You can even see that I got most of my method names from the Akavache API.

The RemoveObject implementation invalidates the object in Akavache. GetObject tries to read the object from the cache, catching any KeyNotFoundExceptions.

Next week I’ll go over how all of this gets plugged into the UI.

Akavache on Win Phone

Akavache is a bit more fiddly on Win Phone.

To start off, install the Akavache nuget package directly in the Win Phone project. Remember, it’s already installed in my PCL project where it is being used, it needs to be installed here as well, even though none of the code reference it directly. At this point, I get my first error:

System.TypeInitializationException was unhandled by user code
  HResult=-2146233036
  Message=The type initializer for 'Akavache.BlobCache' threw an exception.
  Source=Akavache
  TypeName=Akavache.BlobCache
  StackTrace:
       at Akavache.BlobCache.set_ApplicationName(String value)
       at ShoppingCart.WinPhone.Services.WinPhoneCache..ctor()
       at lambda_method(Closure , Object[] )
       at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
  InnerException: System.IO.FileLoadException
       HResult=-2146234304
       Message=Could not load file or assembly 'Splat, Version=1.4.1.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
       Source=Akavache
       StackTrace:
            at Akavache.BlobCache..cctor()
       InnerException:

There is an assembly that can’t be found. Splat is a another package produced by Paul Betts (the producer of Akavache). The problem here is not that the file isn’t there, but that it’s an older version. All I need to do is update the nuget package for Splat and I’m good.

Updating Splat

With this resolved, the next exception I get is that correct version of SQLitePcl.Raw is missing.

System.TypeInitializationException was unhandled by user code
  HResult=-2146233036
  Message=The type initializer for 'Akavache.Sqlite3.Internal.SQLiteConnection' threw an exception.
  Source=Akavache.Sqlite3
  TypeName=Akavache.Sqlite3.Internal.SQLiteConnection
  StackTrace:
       at Akavache.Sqlite3.Internal.SQLiteConnection..ctor(String databasePath, Boolean storeDateTimeAsTicks)
       at Akavache.Sqlite3.SQLitePersistentBlobCache..ctor(String databaseFile, IScheduler scheduler)
       at Akavache.Sqlite3.Registrations.<>c__DisplayClass6.<Register>b__2()
       at System.Lazy`1.CreateValue()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Lazy`1.get_Value()
       at Akavache.Sqlite3.Registrations.<>c__DisplayClass6.<Register>b__3()
       at Splat.ModernDependencyResolver.GetService(Type serviceType, String contract)
       at Splat.DependencyResolverMixins.GetService[T](IDependencyResolver This, String contract)
       at Akavache.BlobCache.get_UserAccount()
       at ShoppingCart.Services.LoginService.get_Users()
       at ShoppingCart.Services.LoginService.<LoginAsync>d__4.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at ShoppingCart.ViewModels.LoginViewModel.<Login>d__0.MoveNext()
  InnerException: System.IO.FileNotFoundException
       HResult=-2147024894
       Message=Could not load file or assembly 'SQLitePCL.raw, Version=0.5.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
       Source=Akavache.Sqlite3
       FileName=SQLitePCL.raw, Version=0.5.0.0, Culture=neutral, PublicKeyToken=null
       StackTrace:
            at Akavache.Sqlite3.Internal.SQLiteConnection..cctor()
       InnerException:

Again this is a nuget package, but this time updating does not fix the problem. I reached out to Paul about the issue and he told me that I have to change the build configuration of the Win Phone project to specify x86 as my platform.

Open Configuraton Manager

Configuraton Manager

Now running the app will work.

Thanks

A big thanks to Paul Betts both for writing Akavache and for providing the last mile of help when I needed it.

Happy Coding

this post was originally on the MasterDevs Blog

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:

Here’s the look I was going for:

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:

Migrate from ActionBarSherlock to AppCompat Create a style for my search box 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 generatorand I’m using the correct themes.

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.

this post was originally on the MasterDevs Blog

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 styled the app so it looked slick. This week I am going to revisit a problem I had in my Day 2 post, namely the lack of an EventToCommand behavior. A developer named Corrado created a Behaviors library specifically for Xamarin.Forms. This library comes with an EventToCommand behavior out of the box, and lets you create your own.

Recap and Code

This is the seventh 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.

Getting Behaviors

First off, you can check out Corrado’s own blog post about this library. You can also take a look at his code on GitHub, or just grab the library from nuget.

The first thing I did was install the nuget package in my core project (ShoppingCart). I did two things wrong here. First, there are two nuget packages to choose from: Xamarin.Behaviors and Xamarin.Forms.Behaviors. Unintuitively, the correct one to choose is Xamarin.Behaviors. The next mistake I made was that I installed it in just the core project. When I ran up the solution, I saw this error immediately:

System.IO.FileNotFoundException was unhandled by user code
Message=Could not load file or assembly 'Xamarin.Behaviors, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

I realized that the platform projects also need to reference the package. Easy enough.

TL;DR

To install behaviors install the nuget package in your shared project as well as all platform projects:

PM> Install-Package Xamarin.Forms.Behaviors

Using Behaviors

My first use case for behaviors is to remove the ugly event to command code I have in my code behind. Here’s the xaml that I want to get rid of:

<ListView ItemsSource="{Binding Categories.Result}"
    IsGroupingEnabled="false"
    ItemSelected="OnItemSelected">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <Label Text="{Binding .}" />
      </ViewCell>
    </DataTemplate>
</ListView>

Specifically, I don’t want the ItemSelected property set to the OnItemSelcted method in the code behind file:

private void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
    var param = e.SelectedItem as string;
    var command = ((CategoriesListViewModel)BindingContext).NavigateToCategory;
 
    if (command.CanExecute(param))
    {
        command.Execute(param);
    }
}

This method casts the context to the view model, grabs the command, casts the SelectedItem into a string to act as the parameter, checks to see if it can call execute, and then calls execute.

First things first, I delete the OnItemSelected method. Gone. No more. Next, I add an EventToCommand behavior in my xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ShoppingCart.Views.CategoriesListPage"
             xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"
             xmlns:local="clr-namespace:ShoppingCart;assembly=ShoppingCart"
             BindingContext="{x:Static local:App.CategoriesListViewModel}"
             BackgroundColor="White">
  <ListView ItemsSource="{Binding Categories.Result}">
    <ListView.ItemTemplate>
      <DataTemplate>
        <TextCell Text="{Binding Name}"
                  Detail="{Binding Count}">
          <b:Interaction.Behaviors>
            <b:BehaviorCollection>
              <b:EventToCommand EventName="Tapped"
                                Command="{Binding NavigateToCategory}"
                                CommandParameter="{Binding Category}" />
            </b:BehaviorCollection>
          </b:Interaction.Behaviors>
        </TextCell>
      </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

There’s a little more going on here than just the behavior, so I’ll explain that first. First off, on line 4, I add the reference to the Behaviors namespace. I also change the DataTemplate from the generic ViewCell to the TextCell. This is mostly just to simplify my layout and because I only recently learned about the TextCell after reading a recent blog on the Xamarin Newsletter. The TextCell lets you create a row in a ListView with a main text field, and a description underneath. I also just realized that the ViewCell and TextCell both already have Command and CommandParameter properties that I could have bound to directly. Evidently I don’t need behaviors for this at all. I’m still going to use behaviors, just so I can play with them a bit. But, if you want to see how to do this without behaviors, check out my list view in the ProductsListPage.

So, now that I have my TextCell, I can use the Interaction.Behaviors attached property and add an EventToCommand behavior. The EventToCommand maps an event on the UI control to an ICommand on the view model. In this case, when the Tapped event of the TextCell is raised, the NavigateToCategory command will be executed. But which NavigateToCategory command? Originally this command existed on the CategoriesListViewModel, but that was when we were in the code behind and our BindingContext was the CategoriesListViewModel. By the time our EventToCommand is created, we are in the DataTemplate and only have access to the individual members of Categories.Results which was originally a list of strings. If we were using WPF, we would have been able to bind to our parent’s context using RelativeSource binding and access the command. RelativeSource binding is not an option in XF. The easiest way around this for me is to change my categories list from strings to CategoryViewModels. Here’s my new view model:

public class CategoryViewModel : BaseViewModel
{
    private readonly Category _category;
 
    public CategoryViewModel(Category category, ICommand navigateCommand)
    {
        _category = category;
        Name = _category.Name;
 
        NavigateToCategory = navigateCommand;
    }
 
    public Category Category { get { return _category; } }
 
    public string Count { get; private set; }
 
    public string Name { get; private set; }
 
    public ICommand NavigateToCategory { get; private set; }
}

The CategoriesListViewModel creates these instances, and just passes the navigate command in. The implementation of the command itself isn’t changed. Truth be told, passing the command in like this is a bit of a hack. It would be cleaner to use the Message Center. That’s a bit out of the scope for this article, perhaps I’ll clean this up next week.

Another thing I’m doing that’s not strictly necessary, is passing in a CommandParameter. I’m just using it here just to show how it can be done. Currently, you can’t pass in the EventArgs as the parameter. There are times when that is useful, so hopefully it’s added some time in the future before I really need it.

What Did I Do Wrong?

Typo in the EventName

At one point in my testing, I had a typo in my EventToCommand where I was trying to bind to a nonexistent event.

<b:EventToCommand EventName="OnTapped"
                  Command="{Binding NavigateCommand}"
                  CommandParameter="{Binding Category}" />

OnTapped doesn’t exist. The correct event name is “Tapped”. This is the error you’ll see if/when you make that mistake:

System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list

The exception is confusing until you look at the EventToCommand code and see that there is a small bug in it when it is trying to throw what would be a much more helpful exception.

Typo in the Command

I also had some trouble with typos where I misspelled the name of the command. This was worse. It just silently doesn’t work. Typos are bad.

Creating Behaviors

Xamarin.Forms.Behaviors comes with two behaviors out of the box: EventToCommand which we discussed earlier, and TextChangedBehavior. Even better though, it gives you all the building blocks you need to create behaviors of your own. Suppose you want to have your Entry (text box) animate when you click in it. Something like this:

Windows Phone Animation

Droid Animation

Here’s the behavior that handles this:

using System;
using Xamarin.Behaviors;
using Xamarin.Forms;
 
namespace ShoppingCart.Behaviors
{
    public class AnimateSizeBehavior : Behavior<View>
    {
        public static readonly BindableProperty EasingFunctionProperty = BindableProperty.Create<AnimateSizeBehavior, string>(
            p => p.EasingFunctionName,
            "SinIn",
            propertyChanged: OnEasingFunctionChanged);
 
        public static readonly BindableProperty ScaleProperty = BindableProperty.Create<AnimateSizeBehavior, double>(
            p => p.Scale,
            1.25);
 
        private Easing _easingFunction;
 
        public string EasingFunctionName
        {
            get { return (string)GetValue(EasingFunctionProperty); }
            set { SetValue(EasingFunctionProperty, value); }
        }
 
        public double Scale
        {
            get { return (double)GetValue(ScaleProperty); }
            set { SetValue(ScaleProperty, value); }
        }
 
        protected override void OnAttach()
        {
            this.AssociatedObject.Focused += OnItemFocused;
        }
 
        protected override void OnDetach()
        {
            this.AssociatedObject.Focused -= OnItemFocused;
        }
 
        private static Easing GetEasing(string easingName)
        {
            switch (easingName)
            {
                case "BounceIn": return Easing.BounceIn;
                case "BounceOut": return Easing.BounceOut;
                case "CubicInOut": return Easing.CubicInOut;
                case "CubicOut": return Easing.CubicOut;
                case "Linear": return Easing.Linear;
                case "SinIn": return Easing.SinIn;
                case "SinInOut": return Easing.SinInOut;
                case "SinOut": return Easing.SinOut;
                case "SpringIn": return Easing.SpringIn;
                case "SpringOut": return Easing.SpringOut;
                default: throw new ArgumentException(easingName + " is not valid");
            }
        }
 
        private static void OnEasingFunctionChanged(BindableObject bindable, string oldvalue, string newvalue)
        {
            (bindable as AnimateSizeBehavior).EasingFunctionName = newvalue;
            (bindable as AnimateSizeBehavior)._easingFunction = GetEasing(newvalue);
        }
 
        private async void OnItemFocused(object sender, FocusEventArgs e)
        {
            await this.AssociatedObject.ScaleTo(Scale, 250, _easingFunction);
            await this.AssociatedObject.ScaleTo(1.00, 250, _easingFunction);
        }
    }
}

This is a big file, but not that much is really going on. AnimateSizeBehavior inherits from Behavior. This means that we can apply it to any type of control. It also means that the AssociatedObject property will be of type View. The key methods to look at are the OnAttach and OnDetach.

protected override void OnAttach()
{
    this.AssociatedObject.Focused += OnItemFocused;
}
 
protected override void OnDetach()
{
    this.AssociatedObject.Focused -= OnItemFocused;
}

OnAttach is called when the behavior is added to the the control and OnDetach is called when it is removed from the control. This is where I registered to receive the Focused event. Now it’s a simple matter that whenever the control gains focus my animation code in OnItemFocused will be called.

private async void OnItemFocused(object sender, FocusEventArgs e)
{
    await this.AssociatedObject.ScaleTo(Scale, 250, _easingFunction);
    await this.AssociatedObject.ScaleTo(1.00, 250, _easingFunction);
}

The animation is very straight forward. I use the ScaleTo method on View to scale the control up, then I call ScaleTo a second time to return it to its original size. If I didn’t want to provide any flexibility with my behavior, I could stop there. The rest of the code is just there to let me pass in parameters and configure how to perform the scale. Let’s look at Scale.

public static readonly BindableProperty ScaleProperty = BindableProperty.Create<AnimateSizeBehavior, double>(
    p => p.Scale,
    1.25,
    propertyChanged: OnScaleChanged);
 
public double Scale
{
    get { return (double)GetValue(ScaleProperty); }
    set { SetValue(ScaleProperty, value); }
}

First I set up a static BindableProperty called ScaleProperty. This is what lets me bind to properties on the behavior. The first parameter ties it to the double Scale instance property. The second parameter sets the default value to 1.25.

The EasingFunction property is a little more complicated. It requires validation when it is set. This is accomplished by setting the propertyChanged parameter in the factory method.

public static readonly BindableProperty EasingFunctionProperty = BindableProperty.Create<AnimateSizeBehavior, string>(
    p => p.EasingFunctionName,
    "SinIn",
    propertyChanged: OnEasingFunctionChanged);
 
private Easing _easingFunction;
 
public string EasingFunctionName
{
    get { return (string)GetValue(EasingFunctionProperty); }
    set { SetValue(EasingFunctionProperty, value); }
}
 
private static void OnEasingFunctionChanged(BindableObject bindable, string oldvalue, string newvalue)
{
    (bindable as AnimateSizeBehavior).EasingFunctionName = newvalue;
    (bindable as AnimateSizeBehavior)._easingFunction = GetEasing(newvalue);
}

The propertyChagned parameter is set to the static OnEasingFunctionChanged method. The instance of the behavior is passed in as the bindable parameter, along with the old and new values being set. In my example, we ignore the old value and just set the new value to the string property of EasingFunctionName. We also parse the new value to determine what type of easing function to use in the GetEasing method. If the easing function supplied is not an expected value, an exception is thrown. This happens not when we try to run the animation, but as soon as we set the value.

Now all I need to do is add the behavior to my text boxes. I’ll do this for the login page because there are two text boxes on the page so we can see how to tweak it.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:bLocal="clr-namespace:ShoppingCart.Behaviors;assembly=ShoppingCart"
             xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"
             x:Class="ShoppingCart.Views.LoginPage" >
  <StackLayout VerticalOptions="FillAndExpand" Padding="50">
 
    <Entry Text ="{Binding Username}" Placeholder ="User name goes here" >
      <b:Interaction.Behaviors>
        <b:BehaviorCollection>
          <bLocal:AnimateSizeBehavior />
        </b:BehaviorCollection>
      </b:Interaction.Behaviors>
    </Entry>
 
    <Entry Text ="{Binding Password}"
      Placeholder ="Password goes here"
      HorizontalOptions="FillAndExpand">
      <b:Interaction.Behaviors>
        <b:BehaviorCollection>
          <bLocal:AnimateSizeBehavior EasingFunction="BounceIn"
                                      Scale="1.50" />
        </b:BehaviorCollection>
      </b:Interaction.Behaviors>
    </Entry>
 
  </StackLayout>
</ContentPage>

I stripped a lot out of the xaml here for clarity (like the submit button). The username textbox has the default behavior set. The password box changes the scale size to 1.5 and selects a different easing function. It would be possible to bind to those values as well, but it didn’t make sense in my already pointless example.

And that’s all there is to it. A quick thanks to lobrien for a useful sample on how to do animations in XF. This sped up my coding quite a bit. And of course a thanks to Corrado for the Xamarin.Forms.Behaviors library.

Happy Coding

this post was originally on the MasterDevs Blog

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 added an dependency injection framework. This week I want to make the app look a little less blah so I’ll be adding themes and styling.

Recap and Code

This is the seventh 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.

Styling Options in XF

The guidance in Xamarin’s documentation is to create custom renders for each control you want to style for each platform. This seemed like an unintuitive and complicated way to go about solving the problem so I avoided trying it as long as possible.

@TheRealJoeRall suggested an interesting idea to try: use the native theming options from each platform. On WindowsPhone add styles with a TargetType but no key to the App.xaml. On Android create a theme in xml and apply it to the top level activity. On iOS use the UIAppearance class. Like the content render solution this approach requires writing a different theme for each platform, but it uses the native approach meaning that there will be more documentation and tooling around it. Now, let’s just hope it works.

Quick Reminder about iOS

Before I go any further, I want to put out a reminder that since I don’t have access to iOS these articles won’t cover it. Which means that I was unable to determine if the UIAppearance class would be able to help in styling a XF application.

Styling Windows Phone

There’s lots of documentation on how to style and theme a native Windows Phone app. Most of it written by people who know a lot more about the topic than I do. I’m going to keep mine to the basics.

The first thing to know is that any styles you create in the App.xaml file will be accessible from all of your content pages by default. But how do you create a style in the first place?

<Application>
  <Application.Resources>
    <ResourceDictionary>
      <Style TargetType="TextBlock" >
        <Setter Property="Foreground" Value="Black"/>
      </Style>
    </ResourceDictionary>
  </Application.Resources>
</Application>

Above is a very simple style that sets the Foreground of all TextBlocks to black. Again, this style can get much more complex, but I’ll leave it here for now.

You could make this an explicit style by giving it a key, x:key=”BlackTextBlock” for example. This way it would only apply to TextBlocks that specifically reference the style. But since all of our pages are currently defined in the common Xamarin Forms layer, we don’t have TextBlocks at all, and can’t reference explicit styles. So while explicit styles are great when writing native Windows Phone pages, they are not very interesting in XF.

Again, I could rant on this a lot longer, but I’m not the best source. My style for WP is quite long but not much more than a basic example, so I won’t bother with the snippet here. If you’re interested, you can view my full App.xaml on GitHub.

Limitations With Using Windows Phone Styling

My goal with the styling was to create a white background. I could not figure out a way to set the background color from within the Windows Phone project. I tried several techniques that did not work.

First, I tried explicitly setting the color in the MainPage.xaml (the following code is stripped down for size and clarity):

<phone:PhoneApplicationPage
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    Background="White" />

This had no effect so I tried setting it programmatically in MainPage.xaml.cs. I tried setting both the MainPage background as well as the navigation page returned from the common layer. Neither worked, either separately or together. I’ll show them all at once.

public MainPage()
{
    this.Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.White);
 
    var startupPage = ShoppingCart.App.StartupPage;
    startupPage.BackgroundColor = Xamarin.Forms.Color.White;
 
    Content = startupPage.ConvertPageToUIElement(this);
}

Digging down into the child page of the navigation page did work, but that had two drawbacks. First it only worked for that one page, so I’d have to change the color of all the pages. Second, it pushed me up into the common layer. Since I was in the common layer anyway it would just be easier to set the background page color directly in the XAML definitions of the pages. This is ultimately what I did. Here’s an example from the Welcome page.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ShoppingCart.Views.WelcomePage"
             BackgroundColor="White" >
   <!-- Layout Removed -->
</ContentPage>

Note that I could have used Xamarin Form’s OnPlatform mechanism to selectively set the property only for Windows Phone. I elected not to since I did want the background to be white on all platforms anyway, even if I did not need to set the property explicitly for Android to work.

Styling Android

Android also has a very simple way to set the overall style for all Activities. They also have much better documentation than I could mimic. The key take away here is to define your android theme in an xml file in the values folder of your project. Then reference it in your AndroidManifest.xml file. The quickest way I’ve found to create a theme is to use the online Holo Colors Generator.

Holo COlor Generator Screen Shot

You just enter the color you want to use in your theme and tick off the checkboxes of the controls you want this theme to apply to. It generates a zip that you can extract directly into your resources directory. Just include all of the files and set your theme in the AndroidManifest like this where AppTheme is the the name of the theme in the themes_apptheme.xml file:

<application android:theme="@style/AppTheme" />

That’s it for styling droid. It’s pretty straight forward and took me about 15 minutes. The color I picked was a nice light green: #afcca6.

Problems with This Approach

One major limitation with this approach is that it treats all things equally All text boxes will look the same. If for example you wanted the text box at the top of the product page to be a color based on the theme, you can’t easily achieve that. You’d have to fallback to manually setting the various properties correctly on each page.

Solution 1: Theme Class

For this specific case, I created an interface IThemer with a default implementation that could be overriden for specific platforms. For now, the only property exposed is AccentColor, but it could be expanded to provide other style related properties.

public interface IThemer
{
    Color AccentColor { get; }
}
 
public class DefaultThemer : IThemer
{
    public Color AccentColor { get { return Color.Accent; } }
}

public class AppSetup
{
    protected virtual void RegisterDepenencies(ContainerBuilder cb)
    {
        // ... Code removed for clarity
        cb.RegisterType<DefaultThemer>().As<IThemer>().SingleInstance();
    }
}

Originally, the DefaultThemer I created just returned a randomly generated dark color and the Windows Phone implementation overrode it with the AccentColor pulled from the app’s resource dictionary. Then while playing around I found the Xamarin.Forms.Color.Accent property. On Windows Phone this returns the phone’s accent color. On Droid it returns black. This is great in that it gets me half way there, but I want to use my nice light green color I defined in my droid styles: #afcca6. So in the droid project I created an implementation of IThemer and registered it with my dependency injection container from last week:

public class DroidThemer : IThemer
{
    public DroidThemer()
    {
        var resources = Forms.Context.Resources;
        int colorId = Resource.Color.apptheme_color;
        var color = resources.GetColor(colorId);
 
        AccentColor = Color.FromRgba(color.R, color.G, color.B, color.A);
    }
 
    public Color AccentColor { get; private set; }
}

public class DroidSetup : AppSetup
{
    protected override void RegisterDepenencies(ContainerBuilder cb)
    {
        base.RegisterDepenencies(cb);
 
        cb.RegisterType<DroidLogger>().As<ILogger>().SingleInstance();
        cb.RegisterType<DroidScanner>().As<IScanner>().SingleInstance();
        cb.RegisterType<DroidThemer>().As<IThemer>().SingleInstance();
    }
}

The code grabs the color as it is defined in my app’s theme and sets the AccentColor property. Now if the color is ever changed in the theme, it will propagate to my special theming class. Again, I simply override the existing registration for the IThemer with the DroidThemer. AutoFac is smart enough to remove the prior registration made in AppSetup.

Now the question becomes, where do I put this class? I could make the BaseViewModel take an instance of it so that all of the views can easily know where to access it. I don’t like this for a number of reasons. First and foremost this is not view model information. It has nothing to do with the state of the app or data, it’s purely view. Secondly, adding constructor parameters on a base class is a headache to mange long term, especially when you wind up having a lot of inheriting classes. You need to touch each child class whenever those parameters change. This is definitely not the solution for me.

My second idea was to expose the AccentColor property on the App class. This really is a system wide app setting so the App class does make a certain amount of sense. Besides, all of my views are already aware of it since that’s where they are getting their view models. Also, it’s really quick to add it in this one place. It’s not an ideal solution since I’m trying to NOT have App turn into a dumping ground for properties (hence my clean up last week) but it’s so quick and easy now, that I’ll go with it.

public static class App
{
    private static IContainer _container;
 
    public static void Init(AppSetup appSetup)
    {
        _container = appSetup.CreateContainer();
        AccentColor = _container.Resolve<IThemer>().AccentColor;
    }
 
    public static Color AccentColor { get; private set; }
}

The init method pulls out the IThemer implementation and grabs the AccentColor from it. After this I bind to the property from within the WelcomePage.

<Label Text="Welcome to The Store"
       Font="Bold, Large"
       HorizontalOptions="Center"
       TextColor="{x:Static local:App.AccentColor}" />

I only used this solution in one place: WelcomePage. While it is good for keeping all of the style definitions in one place I really only had one style that I wanted to use: accent color. As it turned out Xamarin already did most of the heavy lifting for me. Isn’t that always the case?

Solution 2: Color.Accent and OnPlatform

After finding out that I could just use the Color.Accent static color (I really did find that very late in the game), I realized that there was a much simpler way to solve the problem. On platforms that support the Color.Accent, use it, on other platforms use my alternate color. This is easy to accomplish with the OnPlatform class. Here’s an example from my ProductsPage:

<Label Text="{Binding Product.Name}"
       HorizontalOptions="Center"
       Font="Bold,Large">
  <Label.TextColor>
    <OnPlatform x:TypeArguments="Color"
                iOS="Accent"
                WinPhone="Accent"
                Android="#afcca6" />
  </Label.TextColor>
</Label>

On WinPhone and iOS, the Accent color is used. On Droid, I fallback to my custom light green color.

Pics or It Didn’t Happen

I was mostly concerned with the how-to aspect of this write up and avoided screen shots throughout the post. But, now that the post is over, here’s what the app looks like after my styling efforts.

Welcome Screen

WP and Droid Welcome Screens

Categories Screen

WP and Droid Categories Screens

It’s starting to look just a little more polished.

Happy Coding.

this post was originally on the MasterDevs Blog

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 added a product search that uses a barcode scanner using the ZXing component. Today I plan on cleaning up app startup by incorporating a dependency injection framework.

Recap and Code

This is the sixth 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.

Cleanup

Before starting up, I’d like to perform a little bit of clean up. There is a bug in the XF template. When the reference for the platform project (e.g., ShoppingCart.WinPhone) to the core project (i.e., ShoppingCart) is created the project id is missing.

This causes a few subtle problems, the most annoying of which is that renames in the core project are not propagated to the dependent projects. For instance, if I rename the FirstPage property of the App class, the reference in ShoppingCart.WinPhone.MainPage will not be updated.

This can easily be solved by

  1. Removing the reference to ShoppingCart from each of the platform projects
  2. Adding the reference back

As a reminder, to remove the reference, just expand the References node under ShoppingCart.WinPhone in Solution Explorer, select the reference, and hit the delete key.

To add the reference back, right click on the References node, select Add Reference, and tick the checkbox next to ShoppingCart in the Projects tab.

Doing a quick diff of your CSPROJ after this you can see that the Project element has been added to the reference.

<!-- Before -->
<ProjectReference Include="..\ShoppingCart\ShoppingCart.csproj">
    <Name>ShoppingCart</Name>
</ProjectReference>
<!-- After -->
<ProjectReference Include="..\ShoppingCart\ShoppingCart.csproj">
    <Project>{8eb80e50-ef54-451b-9768-3d38e2a3e122}</Project>
    <Name>ShoppingCart</Name>
</ProjectReference>

Dependency Service vs. Injection

Last week I used XF’s DependencyService class to resolve application specific dependencies. This worked by registering the dependency in the Android and WinPhone projects by adding a Dependency attribute like this:

[assembly: Xamarin.Forms.Dependency(typeof(DroidScanner))]

and then resolving it in the core project with a call to DependencyService.Get

var scanner = DependencyService.Get<IScanner>();

While this worked for what I needed last week, it does have the requirement that resolved type (i.e., DroidScanner in my example) has a default constructor. This means that unlike a dependency injection framework, you cannot rely on the framework to create all of your dependencies in one go. You have to manually resolve and compose them yourself.

Dependency Injection on PCL

There are many .Net DI frameworks out there. My go to DI framework is Ninject but as of now it doesn’t support PCL. So, after a little digging for PCL frameworks. The key features that I look for are

  • Constructor injection
  • Registration with generics

I decided to give AutoFac a try. I’ve never used it before, but by looking at the documentation it looked like it meets my requirements.

Starting Up AutoFac

The first thing I need to do is to get AutoFac. In my main project (ShoppingCart) I right click to add a nuget package, search for AutoFac, and cross my fingers that it installs with out complaint. Somewhat to my surprise, NuGet downloaded and added it to my project with out complaint. I know it claimed to be PCL friendly, but I’m always surprised when installing something just works the first time.

Before I remove the usage of DependencyService, I need to configure the rest of the services and view models to be created by the DI framework. I’ll do this in a dedicated class called ContainerCreator. This is a habit I got from Ninject where you can create module classes to do all your bindings. It keeps everything in one place and I like it in Ninject so I’ll see how well it works in AutoFac land.

public class ContainerCreator
{
  public static IContainer CreateContainer()
  {
    ContainerBuilder cb = new ContainerBuilder();
 
    // Services
    cb.RegisterType<LoginService>().As<ILoginService>().SingleInstance();
    cb.RegisterType<ProductLoader>().As<IProductLoader>().SingleInstance();
    cb.RegisterType<ProductService>().As<IProductService>().SingleInstance();
    cb.RegisterType<NavigationService>().As<INavigationService>().SingleInstance();
    cb.RegisterInstance(DependencyService.Get<IScanner>()).As<IScanner>().SingleInstance();
 
    // View Models
    cb.RegisterType<CategoriesListViewModel>().SingleInstance();
    cb.RegisterType<LoginViewModel>().SingleInstance();
    cb.RegisterType<ProductsListViewModel>().SingleInstance();
    cb.RegisterType<ProductViewModel>().SingleInstance();
    cb.RegisterType<WelcomeViewModel>().SingleInstance();
 
    return cb.Build();
  }
}

I’m setting up all of my registrations for my services which implement interfaces and my view models which are registered to themselves. I’m also registering everything as singletons which will probably change later, but this should get me going. Again, I’m still using the DependencyService to get my IScanner, this is just an intermediary step for now. The goal is to remove that by the end of this post.

Next, I’ll clean up App to make use of the AutoFac container

private static readonly IContainer _container;
 
static App()
{
    _container = ContainerCreator.CreateContainer();
 
    NaviService = _container.Resolve<INavigationService>() as NavigationService;
 
    // Pages
    WelcomePage = new WelcomePage();
    LoginPage = new LoginPage();
    CategoriesListPage = new CategoriesListPage();
}

The view model properties now just resolve their values directly from the container when called. They are all pretty much the same, here’s one as an example.

public static CategoriesListViewModel CategoriesListViewModel
{
    get
    {
        return _container.Resolve<CategoriesListViewModel>();
    }
}

Starting the app up, it should work exactly like it did before. And it does. Success.

Removing DependencyService

Now we can get to work on removing the DependencyService. Technically though there is no reason just yet to remove it. It works just fine for my app because DroidScanner and WinPhoneScanner both have parameterless constructors. So I’m going to break it now by adding some parameters. The most common parameter in most of my apps is a logger, so I’ll add one here.

I’ll add ILogger, an interface for my logger:

public interface ILogger
{
    void Info(string message);
    void Info(string format, params object[] args);
    void Info(Exception ex, string message);
    void Info(Exception ex, string format, params object[] args);
 
    void Error(string message);
    void Error(string format, params object[] args);
    void Error(Exception ex, string message);
    void Error(Exception ex, string format, params object[] args);
}

And then a Droid and WinPhone specific implementations each using their platform specific methods for logging: Log and Debug.WriteLine respectively. They are kind of long and boring, so here’s just a simple example from both:

public class DroidLogger : ILogger
{
    private const string APP_NAME = "ShoppingCart";
 
    public void Info(string message)
    {
        Log.Info(APP_NAME, message);
    }
}
public class WinPhoneLogger : ILogger
{
    public void Info(string message)
    {
        Console.WriteLine("INFO:  " + message);
    }
}

Next we add logging to each of the IScanner implementations. Here’s the WinPhone implementation, the Droid version is identical

private readonly ILogger _logger;
 
public WinPhoneScanner(ILogger logger)
{
    _logger = logger;
}
 
public async Task<ScanResult> Scan()
{
    _logger.Info("Starting the barcode scanner.  Stand back.");
 
    var scanner = new MobileBarcodeScanner(MainPage.DispatcherSingleton);
    // ...
}

Hooray, the call to DependencyService.Get now fails with this error: System.MissingMethodException: No parameterless constructor defined for this object. Time to fix it.

First I’m going to change the name of the ContainerCreator to AppSetup and make it a non-static class. My plan is to enable custom app setup by overriding methods in this object. Here’s what it looks like now:

public class AppSetup
{
    public IContainer CreateContainer()
    {
        ContainerBuilder cb = new ContainerBuilder();
        RegisterDepenencies(cb);
        return cb.Build();
    }
 
    protected virtual void RegisterDepenencies(ContainerBuilder cb)
    {
        // Services
        cb.RegisterType<LoginService>().As<ILoginService>().SingleInstance();
        cb.RegisterType<ProductLoader>().As<IProductLoader>().SingleInstance();
        cb.RegisterType<ProductService>().As<IProductService>().SingleInstance();
        cb.RegisterType<NavigationService>().As<INavigationService>().SingleInstance();
 
        // View Models
        cb.RegisterType<CategoriesListViewModel>().SingleInstance();
        cb.RegisterType<LoginViewModel>().SingleInstance();
        cb.RegisterType<ProductsListViewModel>().SingleInstance();
        cb.RegisterType<ProductViewModel>().SingleInstance();
        cb.RegisterType<WelcomeViewModel>().SingleInstance();
    }
}

The registrations have been moved to a dedicated method RegisterDependencies which takes the ContinerBuilder to use to add your registrations. I’ve removed the instance registration that was was using the XF DependencyService (that was the goal the whole time). If you notice, the method is virtual. The idea is to override this for each platform that needs to. Here’s the WinPhone override (the Droid version is very similar):

public class WinPhoneSetup : AppSetup
{
    protected override void RegisterDepenencies(ContainerBuilder cb)
    {
        base.RegisterDepenencies(cb);
 
        cb.RegisterType<WinPhoneLogger>().As<ILogger>().SingleInstance();
        cb.RegisterType<WinPhoneScanner>().As<IScanner>().SingleInstance();
    }
}

All that I’m doing here is registering the WinPhone logger and scanner. The two bits of platform specific implementations that I have. Notice that I call into my base implementation to handle all of the rest of the registrations.

There’s a small problem though. The WinPhoneSetup class won’t compile. It doesn’t know anything about AutoFac. Right now only my core project references AutoFac. I could just add a reference for the WinPhone project, but I know that all of the other projects will need one as well, so I’ll add a reference for each of the projects in one go. The easiest way to do this is to right click on the Solution (not the projects) and select Manage NuGet Packages for Solution. From there you can select the Installed Packages tab and click the “Manage” button for AutoFac. Then just tick all of the check boxes and click OK.

Next in order to have App be able to use different versions of AppSetup I change the static constructor to a static method called Initialize that takes the AppSetup object to use.

public static void Init(AppSetup appSetup)
{
    _container = appSetup.CreateContainer();
 
    NaviService = _container.Resolve<INavigationService>() as NavigationService;
 
    WelcomePage = new WelcomePage();
    LoginPage = new LoginPage();
    CategoriesListPage = new CategoriesListPage();
 
    // Startup Page
    StartupPage = WelcomePage;// CategoriesListPage;
}

Now all I need to do is to call Init from the Droid and WinPhone projects. In MainActivity.OnCreate we add the call Init with the DroidSetup object

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
    Xamarin.Forms.Forms.Init(this, bundle);
    App.Init(new DroidSetup());
    SetPage(App.StartupPage);
}

And in the constructor for MainPage.xaml.cs we call Init with an instance of WinPhoneSetup.

public MainPage()
{
    InitializeComponent();
    Forms.Init();
 
    App.Init(new WinPhoneSetup());
    Content = ShoppingCart.App.StartupPage.ConvertPageToUIElement(this);
}

With AutoFac in place I can delete the two ServiceRegistration classes I had that registered my classes with the DependencyService. And now all I have to do is to spin up the app and see that the log messages in the console.

Happy Coding

this post was originally on the MasterDevs Blog

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 worked I added asynchronously loaded images to a list view. Today I plan on adding a product search that uses a barcode scanner using the ZXing component.

Recap and Code

This is the fifth 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.

Before I implement search with a barcode, it’ll be easier if I add a search box. For now, I’ll just add it on the categories page. This should be simple, I’ll throw up a text box and a button.

<StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal">
  <Entry Text="{Binding SearchTerm}"
         Placeholder="Search"
         HorizontalOptions="FillAndExpand" />
  <Button Text ="Search"
    Command="{Binding SearchCommand}" />
</StackLayout>

Next I wire them into the view model.

private readonly RelayCommand _searchCommand;
 
public CategoriesListViewModel(IProductService service, INavigationService navi)
{
    _searchCommand = new RelayCommand(async () =>
    {
        var items = (await _service.Search(SearchTerm))
                    .OrderByDescending(i => i.Rating)
                    .ToList();
 
        if (items != null && items.Any())
        {
            Page page = items.Count == 1
                 ? page = App.GetProductPage(items.First())
                 : page = App.GetProductsListPage(items, SearchTerm);
 
            await _navi.PushAsync(page);
            SearchTerm = string.Empty;
        }
        else
        {
            await _navi.DisplayAlert("Error", "No results for search " + SearchTerm);
        }
    },
    () => !string.IsNullOrWhiteSpace(SearchTerm));
}
 
public ICommand SearchCommand { get { return _searchCommand; } }
 
public string SearchTerm
{
    get { return GetValue<string>(); }
    set
    {
        SetValue(value);
        _searchCommand.RaiseCanExecuteChanged();
    }
}

If our search has exactly one result, then we go directly to that product page; if there are multiple results, we show them in a list.

The ProductService already has a stub for search, but was only half implemented.

public async Task<List<Product>> Search(string searchString)
{
    var items = await _itemsAsync;
 
    if (string.IsNullOrWhiteSpace(searchString)) return items;
 
    searchString = searchString.ToLower();
    var filterd = items.Where(i => i.Name.ToLower().Contains(searchString))
                       .ToList();
 
    return filterd;
}

Adding a Component

The first step in using a component is to add it to your project. Right click on the “Components” folder in your Droid or iOS project and select “Ge More Components…”

I searched for a barcode scanner and got a list of packages. ZXing sounds familiar and supports all platforms so I go with that.

Window’s phone is a little simpler in that I can just download the package from NuGet:

Install-Package ZXing.Net.Mobile

Using a Component

Since each platform references its own implementation of the barcode scanner software, I now need to create a device agnostic interface in the common project.

public interface IScanner
{
    Task<ScanResult> Scan();
}
 
public class ScanResult
{
    public string Text { get; set; }
}

I then implement these interfaces for each of the platforms.

Android first:

public class DroidScanner : IScanner
{
    public async Task<ScanResult> Scan()
    {
        var scanner = new MobileBarcodeScanner(Forms.Context)
        {
            UseCustomOverlay = false,
            BottomText = "Scanning will happen automatically",
            TopText = "Hold your camera about \n6 inches away from the barcode",
        };
 
        var result = await scanner.Scan();
 
        return new ScanResult
        {
            Text = result.Text,
        };
    }
}

The MobileBarcodeScanner takes the current instance of the Android context. Because this is a common requirement in Android API’s Xamarin exposes the current context in the static property Forms.Context.

WindowsPhone is essentially the same, just a different constructor:

public class WinPhoneScanner : IScanner
{
    public async Task<ScanResult> Scan()
    {
        var scanner = new MobileBarcodeScanner(MainPage.DispatcherSingleton)
        {
            UseCustomOverlay = false,
            BottomText = "Scanning will happen automatically",
            TopText = "Hold your camera about \n6 inches away from the barcode",
        };
 
        var result = await scanner.Scan();
 
        return new ScanResult
        {
            Text = result.Text,
        };
    }
}

Next I register the device specific implementations with the XF DependencyService. In my Droid project I create a file called ServiceRegistration and add the following lines

using ShoppingCart.Droid.Services;
 
[assembly: Xamarin.Forms.Dependency(typeof(DroidScanner))]

A similar file is created for WP:

using ShoppingCart.WinPhone.Services;
 
[assembly: Xamarin.Forms.Dependency(typeof(WinPhoneScanner))]

Now to create an instance of IScanner I resolve it from the DependencyService:

IScanner scanner = DependencyService.Get<IScanner>();

Now all I have to do is wire up a new button to to launch the scanner and use the results.

ScanCommand = new RelayCommand(async () =>
{
    var result = await _scanner.Scan();
 
    SearchTerm = result.Text;
    Search();
});

The scan command just calls into the search implementation I wrote above.

Adding Permissions

And finally, I just need to add in the permission to access the camera, otherwise the barcode scanner component won’t be able to start up at all. On Windows phone open up the WMAppManifest, switch to the Capabilities tab, and make sure that ID_CAP_ISV_CAMERA is checked.

Or just edit the file by hand and add the permission by hand.

<Capability Name="ID_CAP_ISV_CAMERA" />

Android is similar. Right click the project, select Properties, go to the Android Manifest tab, and select CAMERA in the Required permissions section.

Again, you can do this manually by editing the AndroidManifest.xml file directly and adding the CAMERA permission.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
  <uses-sdk />
  <application></application>
  <uses-permission android:name="android.permission.CAMERA" />
</manifest>

Happy coding

this post was originally on the MasterDevs Blog

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 worked through some bugs in XF’s binding and cleaned up the layout a bit. Today the plan is to add product photos to make the list of products and the product pages look prettier.

Recap and Code

This is the fourth 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)

The latest version of the code can always be accessed on the GitHub project page.

Bugs fixed

Last week I ran into a known bug where XF wasn’t properly responding to IPropertyChaged events. At the time there was a fix in a beta build of Xamarin.Forms but I had trouble getting the beta dlls to run in my app. Since then the fix has been officially released. So, I updated all my nuget packages; lo and behold binding now works as expected.

Long story short: Xamarin fixed the bug quickly and correctly. Good for them.

Cleaning the Data

A little nitpicky, but while playing with my app I noticed that the product names don’t look like product names. They are all lower cases and have odd punctuation. I wanted to clean this up quickly so I grabbed Humanizer and added some post processing on the client after loading the products.

item.Name = item.Name
                .Titleize()
                .Replace(".", string.Empty);
item.Description = item.Description
                       .Humanize(LetterCasing.Sentence);

Now, if I want to show “product pictures” I’ll need to get those photos from somewhere. From an unrelated undertaking I had a list of 300+ photos from Imgur. Imgur also has a nice feature where you can request the image as an icon or full size. My data lives in a single string of json which is deserialized at startup. I want to be lazy and not update each item in that list manually so I’m taking a shortcut. I added the Imgur ids to a queue and then in my post-process of the item, I add the icon and image urls. Note the “s” at the end of the IconUrl. That’s Imgur’s way to specify a “small square” icon.

private static void UpdateItem(Product item, string imgurId)
{
    item.ImageUrl = string.Format("http://i.imgur.com/{0}.jpg", imgurId);
    item.IconUrl = string.Format("http://i.imgur.com/{0}s.jpg", imgurId);
}

Now that I have all my data, I’ll start displaying the photos.

Inserting Images

I’m going to start with adding the image to the product page. it’s just one image on the page so it should be pretty simple.

<ScrollView>
  <StackLayout VerticalOptions="FillAndExpand" Padding="50">
 
    <Label Text="{Binding Product.Name}"
      HorizontalOptions="Center"
      Font="Bold,Large" />
 
    <Image Aspect="AspectFill"
            HorizontalOptions="FillAndExpand"
            Source="{Binding Product.ImageUrl}" />
 
    <Label Text="{Binding Product.Description}"
      HorizontalOptions="Start"
      Font="Medium" />
 
    <Label Text="{Binding Product.Price, StringFormat='{0:c}'}"
      HorizontalOptions="Start"
      Font="Bold,Medium" />
 
  </StackLayout>
</ScrollView>

All I needed to do was add an Image element and bind the source to the product’s ImagUrl property. The image will automatically be downloaded and cached for me. According to the documentation the cache lasts one day by default but is configurable. You can even turn the cache off.

This worked pretty well out of the box, everything loaded up very quickly. The only caveat is that some of my pictures are fairly long so the description and text are pushed off the page. Wrapping the entire StackLayout in a ScrollView allows me to scroll down and see the rest of my content.

Moving to the list view, all I do was bind against the IconUrl in the Product model class. Remember, this is the smaller thumbnail provided to us by Imgur.

<ListView ItemsSource="{Binding Products}" ItemSelected="OnItemSelected">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <StackLayout VerticalOptions="FillAndExpand" Orientation="Horizontal" Padding="10">
 
          <Image Aspect="AspectFill"
                 HeightRequest ="75" WidthRequest="75"
                 Source="{Binding IconUrl}" />
 
          <Label Text="{Binding Product.Name}" YAlign="Center" Font="Large" />
        </StackLayout>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

I know I want the images to all be the same size so I set the width and height to be 75 pixels. The Aspect property will do its best to show as much of the image as possible, clipping it where needed. As you can see, I also needed to add a horizontal StackLayout because the data template now has two items in it. I’ve also upped the text size from before, it was hard to click an item in the list because it was too small.

Here’s the result:

It doesn’t look too bad, but there is a problem: it takes a long time to load. Since XF synchronously loads the images, the app is completely blank and unresponsive for 2 to 5 seconds.

Researching the Slow

The app hanging when loading a product list is unacceptable. So the first thing I did to counteract this was to take the network out of the equation. I added a loading image as a resource to the app. Since I wanted the same image on all platforms, I added it directly to the PCL project as an EmbeddedResource.

Just for testing, I modified my model to expose this image instead of the image from the web and bound my view to that instead.

public ImageSource IconSource
{
    get
    {
        string resource = "ShoppingCart.Resouces.placeholderImageSmall.png";
        return ImageSource.FromResource(resource);
    }
}
<Image Aspect="AspectFill"
       HeightRequest ="75" WidthRequest="75"
       Source="{Binding IconSource}" />

The resource path is separated by dots and includes the assembly name as well as any sub folders. In my example above, the file “placeholderImageSmall.png” is in the “Resources” folder (which I created) in the “ShoppingCart” project.

With this change, the page loads instantly, but doesn’t look quite as nice since every product is using the same placeholder image.

Since XF doesn’t do the load asynchronously, I need to figure out how to display the loading icon while the image is downloaded from the web in the background.

If I was in a pure WPF world, I’d use Priority Binding. This lets you set a list of locations to get the binding value from, marking some as asynchronous. Sadly, this is not supported in XF, so that’s right out.

So this means I need to roll it by hand.

Speeding Things Up

I already have a class that manages binding to the result of a task. I used this last time for my product list which is (theoretically) coming from a slow source. It is Stephen Cleary’s NotifyTaskCompletion. This is a good start, but it returns null as the result until the task completes. In my case I want it to return a default value (my place holder image). I tweak the constructor and the result property just a touch to get the implementation I want.

private readonly TResult _defaultResult;
 
public NotifyTaskCompletion(Task<TResult> task, TResult defaultResult = default(TResult))
{
    _defaultResult = defaultResult;
    Task = task;
 
    if (!task.IsCompleted)
    {
        var _ = WatchTaskAsync(task);
    }
}
 
public TResult Result
{
    get
    {
        return (Task.Status == TaskStatus.RanToCompletion)
          ? Task.Result
          : _defaultResult;
    }
}

The constructor now takes the default value, with a default value of default(TResult) so we don’t break any existing uses of the class.

Next a few helpers to make using this for images simple:

public static class AsyncImageSource
{
    public static NotifyTaskCompletion<ImageSource> FromTask(Task<ImageSource> task, ImageSource defaultSource)
    {
        return new NotifyTaskCompletion<ImageSource>(task, defaultSource);
    }
 
    public static NotifyTaskCompletion<ImageSource> FromUriAndResource(string uri, string resource)
    {
        var u = new Uri(uri);
        return FromUriAndResource(u, resource);
    }
 
    public static NotifyTaskCompletion<ImageSource> FromUriAndResource(Uri uri, string resource)
    {
        var t = Task.Run(() => ImageSource.FromUri(uri));
        var defaultResouce = ImageSource.FromResource(resource);
 
        return FromTask(t, defaultResouce);
    }
}

All this is doing, is creating (and running) a task to download the images in the background and feeding that into the NotifyTaskCompletion. One caveat here is that even if nothing ever binds to the image, it will still be downloaded. The ProductViewModel can now expose the IconUrl as an asynchronous wrapper around an ImageSource

public class ProductViewModel : BaseViewModel
{
    private const string _resource = "ShoppingCart.Resources.placeholderImageSmall.png";
    public ProductViewModel(Product product)
    {
        Product = product;
        IconSource = AsyncImageSource.FromUriAndResource(product.IconUrl, _resource);
    }
 
    public NotifyTaskCompletion<ImageSource> IconSource { get; private set; }
 
    public Product Product
    {
        get { return GetValue<Product>(); }
        set { SetValue(value); }
    }
}

The ProductsListViewModel will have to expose a list of the ProductViewModel instead of just the raw model which is a shame. I like binding to the model whenever possible just so I don’t have to worry about passing view models around. But what can you do? And now in the view, we bind to the result of the IconSource like so:

<Image Aspect="AspectFill"
       HeightRequest ="75" WidthRequest="75"
       Source="{Binding IconSource.Result}" />

Expectations and Realities

Running up the app my expectation would be to see the loading images when you first go to the product list pages and over the course of 2 to 5 seconds have them change to the correct product images as they are downloaded. In reality, when I navigated to a page all of the photos were present immediately. Right away. No delay. No loading images.

Happy coding.

this post was originally on the MasterDevs Blog

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 got some basic binding setup and navigation working. Today I plan on cleaning up the views a bit so that they look “nice”. Well nicer. After that I’d like to show a list of products and let the user drill in and look at details.

Recap and Code

This is the third 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)

The latest version of the code can always be accessed on the GitHub project page.

Cleaning up Login and Main Page

Last time I was focused on functionality. I was happy to just get the pages to do what I want. Now i want to take a little time and play with the layout a bit. First on the docket is “MainPage”. It really isn’t the main page, so I’ll rename that to “WelcomePage”. This includes the the view model as well.

With that done I want to add some space around all of the text box and button. Problem is: there’s no “margin” property on any of the controls. After a little digging, it seems that the only way to add spacing is to wrap each control in its own ContentView and set the Padding property on that. A slightly simpler approach is to use a Frame instead. It inherits directly from ContentView and has a default padding of 20. Despite the fact that this only saves me from setting one property, the fact that it’s in a Frame helps me remember why I’m wrapping the control in the first place. Let’s wait a few weeks and see if I continue using Frames.

The WelcomePage (né MainPage) now looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ShoppingCart.Views.WelcomePage"
             xmlns:local="clr-namespace:ShoppingCart;assembly=ShoppingCart"
             BindingContext="{x:Static local:App.WelcomeViewModel}">
 
  <StackLayout
    VerticalOptions="Center">
    <Frame>
      <Label Text="Welcome to The Store" Font="Bold, Large" HorizontalOptions="Center" />
    </Frame>
 
    <Label Text="Login to start shopping" HorizontalOptions="Center" />
 
    <Frame>
      <Button Text ="Log In" Command="{Binding GoToLoginPageCommand}" HorizontalOptions="Center" />
    </Frame>
  </StackLayout>
</ContentPage>

I also tweaked the welcome text making it bigger and bold as well as adding a call to action to help the user navigate to their next step. There’s a fair bit you can do with the Font (size, style) property just by providing a comma separated list of values.

The login page got the same spacing treatment, including a nice fat margin around the entire page just so the text boxes don’t sit flush against the right side. It’s still a little stark so I’ll throw in a touch of color on the title text, just because I can.

<StackLayout VerticalOptions="FillAndExpand" Padding="50">
 
<Frame Padding="75">
  <Label Text="Login"
    Font="Bold,Large"
    TextColor="Yellow"
    HorizontalOptions="Center" />
</Frame>
 
<Label Text="User name"
  HorizontalOptions="Start" />
<Entry Text ="{Binding Username}"
  Placeholder ="User name goes here"
  HorizontalOptions="FillAndExpand" />
 
<Label Text="Password"
  HorizontalOptions="Start" />
<Entry Text ="{Binding Password}"
  Placeholder ="Password goes here"
  HorizontalOptions="FillAndExpand" />
 
<Button Text ="Log In"
  Command="{Binding LoginCommand}"
  HorizontalOptions="CenterAndExpand" />
 
</StackLayout>

Now that looks a little bit nicer.

Data

Now that the two pages I have look reasonable, I’ll add another. In order to show some data, I actually need data. To keep it simple, I start off by creating a list of hard coded C# data. I have to admit that I got a bit silly here. At first I tried to hand craft a back log of data. That got old really fast. In fact I only got one item defined before I realized I was wasting a lot of time. Next I decided to grab a list of products (books) from the web and just tweak the data to my needs. This too proved onerous. Then I broke down and went to the web to generate all of my data. I found a great site that even outputs the data in JSON. It was the first hit on Google. To process the JSON i nuget and install Newtonsoft’s Json.NET.

I add a ProductLoader and a ProductService class. The loader simply stores the literal string of JSON and deserializes it on request. In the future I want to create another implementation that reads the data from disk or the web. The ProductService doesn’t care where the data comes from, it provides the view models with an interface to query and filter the data. Because the underlying data will eventually come from a web request, both of these services asynchronously return Tasks. I use Stephen Cleary’s NotifyTaskCompletion in my view model to consume these services. For a detailed explanation of what’s going on here, take a look at his Patterns for Asynchronous MVVM Applications series.

The data object itself is pretty simple.

public class Item
{
    public string Category { get; set; }
    public string Description { get; set; }
    public string ImageUrl { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public string ProductCode { get; set; }
    public int Rating { get; set; }
    public List<string> Tags { get; set; }
}

The Category property lets us show a short list to the user once they log in. Once they pick a category they see all of the items in that category and then drill down into a specific item. To accommodate this flow, I’ll add three more pages with corresponding view models:

  • CategoriesListPage/ViewModel
  • ProductsListPage/ViewModel
  • ProductPage/ViewModel

With a bigger app I’d lean towards single instances of each of these pages and using a message broker to update one from the other. I..e, when a category is clicked on in the CategoriesList page I’d send an “Update List of Products” message and then navigate to the ProductsPage. But since I already have the convenient App.cs handling all of my interactions between pages, I’ll just squash it into there. Not ideal for a larger app that I’d like to keep decoupled, but fine for the five pages I currently have.

Lists and DataTemplates

The first thing to tackle is to show the list of categories. This is similar to traditional two step process in Windows XAML. Step one: bind the ItemsSource property to the list. A quick reminder that the Categories property is a [NotifyTaskCompletion<List>](http://msdn.microsoft.com/en-us/magazine/dn605875.aspx) which means I need to bind against Categories.Result. Step two: define a data template to define how each row looks. Strictly speaking, since my underlying data is a string, I can skip this step. Since this is my first time defining a data template in XF, I’ll define one anyway just to make sure it works how I expect. In my example I’m making the background color red just so I can verify that it’s using my DataTemplate.

<ListView ItemsSource="{Binding Categories.Result}" ItemSelected="OnItemSelected">
   <ListView.ItemTemplate>
      <DataTemplate>
         <ViewCell>
            <Label Text="{Binding .}" BackgroundColor = "Red" YAlign="Center" Font="Medium" />
         </ViewCell>
      </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

Handling Events

You’ll notice in the above definition of my ListView that I’m setting the ItemsSelected event handler. I’m not binding against the view model here, I’m calling into code behind which then calls into my view model.

public partial class CategoriesListPage
{
    public CategoriesListPage()
    {
        InitializeComponent();
    }
 
    private void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        var param = e.SelectedItem as string;
        var command = ((CategoriesListViewModel)BindingContext).NavigateToCategory;
 
        if (command.CanExecute(param))
        {
            command.Execute(param);
        }
    }
}

This is a lot of boilerplate code for handling a click. The problem is that the ListView doesn’t expose a command I can bind against when an item is selected. In a traditional Xaml app I’d use the EventToCommand pattern except that it is built on Blend behaviors which aren’t PCL compatible and therefore not Xamarin compatible.

Another option was to subclass the ListView class and expose the command logic that I need. I might eventually go this route, but I’ll probably need more than a few list boxes in my app to justify it.

Binding Bug in XF

The command for navigating to a category’s page gets a list of all the items for that category and calls into the static App class to get the page to navigate to.

var page = App.GetProductsListPage(items, categoryName);
await _navi.PushAsync(page);

Originally App.cs just updated the properties on the view model and returned the single instance of the ProductsListPage.

public static Page ProductsListPage { get; private set; }
 
public static Page GetProductsListPage(List<Item> items, string title)
{
    if (string.IsNullOrWhiteSpace(title)) title = "Products";
 
    ProductsListViewModel.Products = items;
    ProductsListViewModel.Title = title;
    return ProductsListPage;
}

This relies on the binding to update the view when something has changed and INotifyProperty.PropertyChanged is raised. The first time this is called it works just fine. It fails on all subsequent calls. After a lot of debugging and assuming that I was wrong I found a recent post on Xamarin’s forums explaining that there is a bug where the UI is not updated when a bound value is changed. Note that this only effects values that are updated in the view model updating on the view; the other way works just fine. Updating a value in the view (like a text entry) correctly updates the bound value in the view model. This is why my login page worked just fine.

Xamarin has released a fix for this bug, but as of writing this it is in a pre build of XF. I tried to use it but kept getting runtime DLL errors. I tried several times before having to give up on this as an immediate solution. I will say that this may have just been an issue with user error since it was close to 1 AM at this point.

In my specific case, there was no reason that I had to reuse the same view. Simply recreating the view every time I wanted to display it was simple enough.

public static Page GetProductsListPage(List<Item> items, string title)
{
    if (string.IsNullOrWhiteSpace(title)) title = "Products";
 
    ProductsListViewModel.Products = items;
    ProductsListViewModel.Title = title;
}

Summary

Today I was able to clean up some of the views using the Frame control to provide margins. I had to resort to two workarounds, one for routing events to commands in code behind the other for updating the view when a bound value has changed.

I’m not sure what I want to tackle next week. Perhaps reading from the file stream? Maybe fleshing out the products view a bit so I display an image to go with the product?

Until then, happy coding.

this post was originally on the MasterDevs Blog

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 we did little more than get our feet wet. The plan for today is to create a page with data binding At this stage of the app, that sounds like a login page to me.

An aside. It got rather tiring saying “Xamarin.Forms” all the time and I’m not quite comfortable just calling it “Forms” because I keep thinking back to WinForms whenever I do. So I’m just going to go the abbreviation route and call it XF. The abbreviation has the benefit of starting with an “X” and those are just cool.

Recap and Code

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

  • Day 0: Getting Started (blog / code)
  • Day 1: Binding and Navigation (blog / code)

The latest version of the code can always be accessed on the GitHub project page.

Binding

Before I’m able to do anything fancy, I need to figure out how to do some basic binding. To test this out, I create a basic view model with one property that returns some constant text.

public class MainViewModel
{
    public string Message {get { return "Hello World";}}
}

I update the view to simply bind to this message now instead of hard coding the text in the XAML.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ShoppingCart.Views.MainPage">
    <Label Text="{Binding Message}" HorizontalOptions="Center" />
</ContentPage>

For now, I’ll just set the BindingContext in the page’s constructor.

public partial class MainPage : ContentPage
{
    public MainPage(MainViewModel vm)
    {
        this.BindingContext = vm;
        InitializeComponent();
    }
}

All that’s left is to pass in a new view model when creating the page.

new MainPage(new MainViewModel())

Firing up the emulator, this works out of the gate. Nice. Time to move on to something a little more difficult.

The Main Page

I don’t want the login page to be the first page of the app. I think some sort of splash screen or welcome message would make more sense. For now It will simply just have some text and a button that’ll take you to the login page. I’ll add the standard Command=”{Binding GoToLoginPageCommand}” now and wire it up next.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ShoppingCart.Views.MainPage"
             xmlns:local="clr-namespace:ShoppingCart;assembly=ShoppingCart"
             BindingContext="{x:Static local:App.MainViewModel}">
 
  <StackLayout
    VerticalOptions="Center">
    <Label Text="Welcome to the main page." HorizontalOptions="Center" />
 
    <Button Text ="Log In" Command="{Binding GoToLoginPageCommand}" HorizontalOptions="Center" />
  </StackLayout>
</ContentPage>

Now that I know I need to bind to a command, I add the MainViewModel. The command adds some complexity for two reasons. First it’s a command so I need to either implement ICommand or find an already ready implementation. There’s nothing that I could find in XF that implements ICommand for me and I don’t want to bring in an outside framework like MvvmLight just yet so I go ahead and add add a simple implementation of ICommand. It’s so simple that I even named it SimpleCommand.cs. I’m not really sure if this will stay long term, but it’ll do the job for now.

The second bit of complexity isn’t as easy. It’s the fact that I don’t know how to do navigation in XF. So it’s time for some research. To the LIBRARY!

Figuring Out Navigation

According to the doco, all you need to do is wrap your ContentPage in a Navigation page. This is as simple as

new NavigationPage(new MainPage())

Then in your page you can access the Navigation property. After playing with this property a bit I learned that how it works depends on your platform. On Windows Phone it was non null and worked regardless of whether or not you created a NavigationPage. Android was less forgiving. One nice touch was that as soon as you wrap your droid page you get the ActivityBar back button.

Playing around with the Navigation property on the page on both Windows and Android, I found it to be buggy. I set up a simple pair of pages with one button each. The first page would merely navigate to the second page. The second page would just pop the stack and return to the first. With some experimenting it looked to me that the XF infrastructure worked best if you always used the same exact instance of INavigation.

In my opinion, there’s a problem with navigation living in the page. Navigation is important business logic and business logic should not live in the view layer. I don’t want to fight the infrastructure too much but if at all possible, I’m going to want to see what can be done to move navigation to the view model layer.

With this knowledge and my desire to abstract the navigation property out to the view model, I created my own wrapper navigation service.

public class NavigationService : Xamarin.Forms.INavigation
{
    public INavigation Navi { get; internal set; }
 
    public Task<Page> PopAsync()
    {
        return Navi.PopAsync();
    }
 
    public Task<Page> PopModalAsync()
    {
        return Navi.PopModalAsync();
    }
 
    public Task PopToRootAsync()
    {
        return Navi.PopToRootAsync();
    }
 
    public Task PushAsync(Page page)
    {
        return Navi.PushAsync(page);
    }
 
    public Task PushModalAsync(Page page)
    {
        return Navi.PushModalAsync(page);
    }
}

Very simply, it directs all calls to an internal implementation. Again, the static App class is responsible for coordinating the creation of these classes

NavigationService navi = new NavigationService();
MainViewModel = new MainViewModel(navi);
 
MainPage = new NavigationPage(new MainPage());
 
navi.Navi = MainPage.Navigation;

Back to the MainViewModel

Now that we’ve solved the problems of commands and navigation, it’s pretty simple to finish off our MainViewModel.

public class MainViewModel
{
    private readonly INavigation _navi;
 
    public MainViewModel(INavigation navi)
    {
        _navi = navi;
    }
 
    public ICommand GoToLoginPageCommand
    {
        get { return new SimpleCommand(() => _navi.PushAsync(App.LoginPage)); }
    }
}

I left the creation of the login page in the App. This way all my page creation can live in one place.

The Login Page

The login page and view model model are pretty simple. Fields for username and password, and a button to submit. Upon “successfully” logging in we’ll just return back to the the main page. If there’s a failure then we display a message box.

Like navigation, displaying a message box is tightly coupled to the page. I wound up wrapping it up in my Navigation class in a similar fashion as navigation. It’s not really the best spot for it, but it cut down on the number of classes and interfaces i was creating. Also, it was a fast addition. Given the size of the project I don’t really have a problem with it now, but I foresee it being moved out at some point.

Here’s what the navigation interface and implementation look like now:

public interface INavigationService : INavigation
{
    Task<bool> DisplayAlert(string title, string message, string accept, string cancel = null);
}
 
public class NavigationService : INavigationService
{
    public INavigation Navi { get; internal set; }
    public Page myPage { get; set; }
 
    public Task<Page> PopAsync()
    {
        return Navi.PopAsync();
    }
 
    public Task<Page> PopModalAsync()
    {
        return Navi.PopModalAsync();
    }
 
    public Task PopToRootAsync()
    {
        return Navi.PopToRootAsync();
    }
 
    public Task PushAsync(Page page)
    {
        return Navi.PushAsync(page);
    }
 
    public Task PushModalAsync(Page page)
    {
        return Navi.PushModalAsync(page);
    }
 
    public Task<bool> DisplayAlert(string title, string message, string accept, string cancel = null)
    {
        return myPage.DisplayAlert(title, message, accept, cancel);
    }
}

Wiring up ViewModels

A pattern I have always liked from the MvvmLight toolkit is setting up the binding to the view model directly in the view’s XAML. I had to tweak the default MvvmLight template a bit to get this to work, but in the end it wasn’t pretty simple. In the view, create a static binding to a property exposed by the App class. This could be any class, but I went with the App class since it is already being used as a static resource for all of the views anyway.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ShoppingCart;assembly=ShoppingCart"
             BindingContext="{x:Static local:App.LoginViewModel}"
             x:Class="ShoppingCart.Views.LoginPage">
  <!-- Code removed for brevity-->
 
</ContentPage>

This lets us simplify App.cs just a little bit, now that we don’t have to pass in the view models to the views.

public static class App
{
    public static MainViewModel MainViewModel { get; set; }
    public static LoginViewModel LoginViewModel { get; set; }
 
    static App()
    {
        ILoginService login = new LoginService();
        NavigationService navi = new NavigationService();
 
        MainViewModel = new MainViewModel(navi);
        LoginViewModel  = new LoginViewModel(login, navi);
 
        MainPage = new NavigationPage(new MainPage());
        LoginPage = new NavigationPage(new LoginPage());
 
        navi.Navi = MainPage.Navigation;
        navi.myPage = MainPage;
    }
 
    public static Page LoginPage { get; private set; }
    public static Page MainPage { get; private set; }
}

Summary

This is pretty much it for this week. I’ve added binding, commands, and navigation as well as wired up the view models. Next week I’ll flesh out the products pages and try to actually add the shopping cart. Until then, happy coding.

this post was originally on the MasterDevs Blog

This will be the first in a series where I create a shopping cart application using Xamarin.Forms While I have experience using Xamarin and MVVMCross to create applications, I have never used Forms before. This series is intended as a journal of my learning experience where I will point out stumbling blocks and tricks I pick up along the way.

Setting out, I plan to build a cross-platform shopping cart application using XAML using the MVVM design pattern. I’ll focus my tests on Windows Phone because it’s much easier and faster to test but I will also verify that the app works on Android whenever it makes sense. Sadly I don’t have the equipment necessary to test on iPhone.

The source code for this article can be downloaded from Git: ShoppingCart-Day0.zip

Quickly, What is Xamarin.Forms?

Traditionally Xamarin has let you write a WindowsPhone, iOS, and Android apps in C#, letting you share all app logic. You would only need to rewrite your views for each platform, using the device specific controls and paradigms.

With Forms is Xamarin has added a cross platform UI framework. It allows you to define your UI with device agnostic names for common controls. For instance, in Forms you’d use an Entry object instead of the WindowsPhone TextBox or the Android EditText. When run, the app still renders 100% native controls. So even though they share a common UI definition, buttons on WindowsPhone look like WindowsPhones butons; buttons on Android look like Android buttons; Buttons on iPhone look like iPhone buttons.

Getting Started

With all the preliminaries out of the way, let’s create our first app. Fire up Visual Studio (you can use Xamarin Studio if you like, but VS is my home). Go to File-> New-> Project and pick Blank App (Xamarin.Forms Portable). You can use the filter in the top right to find the project template more easily. I’m calling it ShoppingCart.

This will take a second to generate 4 projects for you:

  • ShoppingCart
  • ShoppingCart.Android
  • ShoppingCart.iOS
  • ShoppingCart.WindowsPhone

ShoppingCart is your main project. It is referenced by the other three. At this point you can set any of the device projects (ShoppingCart.Android, ShoppingCart.iOS, ShoppingCart.WindowsPhone) as the startup object and deploy the app to your device or emulator.

ShoppingCart only has one code file in it, App.cs. All this does is create an instance of a Page and return it.

public class App
{
    public static Page GetMainPage()
    {
        return new ContentPage
        {
            Content = new Label
            {
                Text = "Hello, Forms !",
                VerticalOptions = LayoutOptions.CenterAndExpand,
                HorizontalOptions = LayoutOptions.CenterAndExpand,
            },
        };
    }
}

So it seems the Page class is the base of every view, analogous to a WindowsPhone PhoneApplicationPage, iOS UIViewController, or Android Activity. The device specific startup logic grabs the Forms Page object and sets it as it’s startup object. Pretty straight forward.

Starting out with XAML

All I want to accomplish today is to change the definition of that view from C# to XAML. In the ShoppingCart project, I’ll create a new folder called “Views” an add a Forms.Xaml Page named “MainPage”

This is a new item template that you get with the Forms projects. Similar to the PhoneApplicationPage, it’s a XAML file with a code behind. You can see that it inherits from ContentPage, the same type that App.GetMainPage creates.

At this point, I’m starting to notice that Visual Studio is starting to slow down. Switching between tabs and making edits to the .xaml file is sluggish. Now, this may just be my machine. It’s fast, but only has 4GB or RAM. It’s also been acting up in other ways lately and I’ve been meaning to reformat. Since I don’t seem to be getting intellisense in the xaml file, I’ll just switch to an alternative text editor instead. I’ve already set up VS to open files in vim when I hit Ctrl-Alt-V so this isn’t really a big annoyance for me.

This view is supposed to be a simple copy of the one defined in App.cs, so I’ll delete the default Label they give me from the template and replace it with one with some static text. Although, it is nice to note that the sample uses a simple binding for the text property. I wonder where we set what we bind against, but I’ll worry about that later.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       x:Class="ShoppingCart.Views.MainPage">
  <Label Text = "Hello, XAML Forms!"
         VerticalOptions = "CenterAndExpand"
         HorizontalOptions = "CenterAndExpand" />
</ContentPage>

OK, my first bit of Form xaml done and it wasn’t too painful. Now to wire it up. Going back to App.cs, instead of creating a new ContentPage, I new up an instance of MainPage and return that.

public static Page GetMainPage()
{
    return new MainPage();
}

Firing up the emulator, it looks like it works. I changed the text in the label ever so slightly to make it easy to ensure that I know that I’m seeing my changes.

So that’s enough for me to call it a victory and go reward myself with some XBox One.

The source code for this article can be downloaded from Git: ShoppingCart-Day0.zip. Note how it is stunningly close to the default template. Not much changed.

this post was originally on the MasterDevs Blog

Full source for this post can be found on GitHub: HeaderedGridView

Last week I posted about adding a header to a GridView. Today I’ll be discussing how to add a header (and footer!) to a MvxListView. The MvxListView is a data-binding friendly ListView from MvvmCross. Adding a header here is a little different because we need an instance of HeaderViewListAdapter that implements IMvxAdapter . Other than that, the code should be very familiar.

Requirements

Just so it is clear what we are building, here are my requirements for this control:

  1. Ability to add a header and footer to the MvxListView in xml markup
  2. The header is to be laid out inline with the rest of the items, at the top
  3. The footer is to be laid out inline with the rest of the items, at the bottom
  4. The header and footer need to scroll with the rest of the content, i.e., they are not always visible
  5. The header and footer must be able to use MvvmCross bindings
  6. Some quick screenshots from the sample project will help us understand what this should look like.

The list is scrolled to the top with purple header visible

Shows the list at some point in the middle when neither header nor footer is visible

The list scrolled all the way to the bottom with the green footer visible

Code

Full source for this post can be found on GitHub: HeaderedGridView

The MvxListView assumes that the adapter it has implements IMvxAdapter. We can create a simple wrapper class that inherits from HeaderViewListAdapter and implements that interface. The constructor will accept the list of headers and footers like the base class in addition to accepting an IMvxAdapter to wrap. All of the interface methods for IMvxAdapter can then be passed down to the internal adapter.

In the snippet of HeaderMxAdapter above we have two constructors. The first can be used if you do not want to add a footer. It simply calls into the second passing an empty list of footers to add to the adapter. The only other thing the constructor does is to squirrel away the adapter in a private field for later use.

The implementation for DropDownItemTemplateId is simple and indicative of the rest of the methods in the class. It merely calls into that squirreled away adapter, calling its implementation of DropDownItemTemplateId. The rest of the methods are exactly the same and have been omitted for brevity.

Next step is to add a pair of attributes to use for our header and footer. This is exactly the same as the headered grid view and is done in attrs.xml.

Some boiler-plate code in MvxListViewWithHeader will read these values so we know what views to use for the header and footer. Like last time, I’m using some helper classes to do the parsing. They are included in the project.

Next we need to create the views for the header and footer.

First we check if the id is the default header id, if it is then we don’t have a view defined in the xml, and we just return null. After that we get the current binding context and use it to inflate our view. This is the magic that lets us bind within our header and footer.

Once we have the view, we need to wrap it in a list of FixedViewInfo which is what the HeaderMxAdapter expects in its constructor.

Nothing earth shattering here. If the view is null, return an empty list, otherwise construct the FixedViewInfo and add it to the list. Returning an empty list allows us to specify only the header, only the footer, or neither without causing any errors.

A couple of helper methods make help to make it clear and concrete what GetFixedViewInfos does.

All of this is called from the constructor which creates the MvxAdapter and wraps it in our new HeaderMvxAdapter. It then set the adapter property in the base class.

The constructor is also responsible for reading in the item template id which the MvxListView uses to display the individual items in the list.

Using the Control

You would use the MvxListViewWithHeader the same way as a MvxListView. The only difference is that you can now optionally specify a header or footer attribute which would point to another layout. The following is taken from the FirstView in the sample.

The header and footer layout in the sample are very simple. They are just a TextView with the text property bound to the view model. Here is the header layout, but the footer is almost identical.

Future Improvements

Like the headered grid view, this implementation only allows a single header. If we had need for multiple headers we could copy the onFinishedInflate method from ListView. It collects all the child layouts for the list view and adds them to the list of headers.

Happy Coding

this post was originally on the MasterDevs Blog