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

Full source code for this article can be downloaded on GitHub: HeaderedGridView.

For the easy import feature of Yarly, I needed to create a view that would easily allow a user to select an existing photo to import into the app or to take new photo. A grid view of photos from the camera roll but with the first item as a button that would load the camera would serve nicely for this use case. See the screen shot below of an early version of the UI:

Yarly Screen Shots 2014-04-20_194747_242000

This reminded me of the AddHeaderView method available on ListView. With that as a guide, I decided to add similar functionality to the GridView. Since I’m using MvvmCross, I also want to make sure that I can use bindings in the header control. While I’m at it, having to explicitly call AddHeaderView in my activity code is useful, but I’d much rather to be able to do this in markup.

Requirements

To sum up the above requirements:

  1. Ability to add a header to a GridView in xml markup
  2. The header is laid out inline with the rest of the items in the GridView
  3. The header scrolls with the rest of the content, i.e., it is not always visible
  4. The header must be able to use MvvmCross bindings

Code

A full sample project can be downloaded from my GitHub repo: HeaderedGridView.

In attrs.xml, add an attribute to use for our header.

<!-- attrs.xml -->
<declare-styleable name="GridView">

   <attr name="header" format="reference" />
</declare-styleable>

In the HeaderedGridView, all we need to do now is check for the presence of this attribute, and if it exists, inflate the view. Reading the header id is straight forward processing of the IAttributeSet. I use some helper classes to iterate and dispose of the attributes in a more C# way. The details aren’t very important, but the relevant classes are included in the sample solution. The MvvmCross class MvxAndroidBindingContextHelpers can return the current binding context which can be used to inflate and bind the header at the same time.

// HeaderedGridView.cs
private void ProcessAttrs(Context c, IAttributeSet attrs)
{
    _headerId = DEFAULT_HEADER_ID;
    using (var attributes = c.ObtainDisposableStyledAttributes(attrs, Resource.Styleable.GridView))
    {
        foreach (var a in attributes)
        {
            switch (a)
            {
                case Resource.Styleable.GridView_header:
                    _headerId = attributes.GetResourceId(a, DEFAULT_HEADER_ID);
                    break;
            }
        }
    }
}

private void LoadHeader()
{
    if (_headerId == DEFAULT_HEADER_ID) return;
    IMvxAndroidBindingContext bindingContext = MvxAndroidBindingContextHelpers.Current();
    _header = bindingContext.BindingInflate(_headerId, null);
}

Now that we have a header, we can wrap our current adapter in the HeaderViewListAdapter. As the name implies, this is the exact same adapter used by the ListView. It handles knowing when and where to show the header. In my sample code, I have the grid create the adapter directly, but this can work just as well if an adapter is passed in from outside.

// HeaderedGridView.cs 

private IListAdapter GetAdapter()
{
    var headerInfo = GetHeaders();
    ICursor cursor = ImageAdapter.CreateCursor(Context);
    IListAdapter adapter = new ImageAdapter(Context, cursor);

    if (headerInfo != null)
    {
        adapter = new HeaderViewListAdapter(headerInfo, null, adapter);
    }
    return adapter;
}

So I don’t have to hard code sizes and so the header matches the rest of the items in the grid, I set the height and width once the grid is being laid out. In the OnMeasure method we check if the header isn’t null, and if the ColumnWidth doesn’t match the previous column width we saw. Caching the width and testing this prevents us from setting the layout parameters when we don’t have to; OnMeasure is called multiple times.

// HeaderedGridView.cs
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    base.OnMeasure(widthMeasureSpec, heightMeasureSpec);

    if (_header != null && base.ColumnWidth != _cachedColumnWidth)
    {
        _cachedColumnWidth = base.ColumnWidth;
        _header.LayoutParameters = new ViewGroup.LayoutParams(_cachedColumnWidth, _cachedColumnWidth);
    }
}

Now all we need to do is include our grid in a layout. It’s almost exactly the same as the regular GridView, except we can now optionally specify a header. This is from the FirstView layout in the sample.

<!--FirstView.axml-->
<HeaderedGridView
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:layout_weight="1"
   android:numColumns="3"
   android:verticalSpacing="10dp"
   android:horizontalSpacing="10dp"
   android:stretchMode="columnWidth"
   android:gravity="center"
   android:fastScrollEnabled="true"
   android:background="#000000"
   local:header="@layout/gridheader" />

The gridheader layout is just a simple layout with a single image button button. Note that we are binding the click of the button to the ClickCommand in our view model.

<?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"
    android:padding="5dp">
    <ImageButton
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="#90C53E"
        android:src="@drawable/camera"
        local:MvxBind="Click ClickCommand" />
</LinearLayout>

Firing up the sample solution and we should see something similar to:

Future Improvements

My implementation restricts me to only being able to add one header. While one header is currently good enough for me, if I wanted to expand it add more, I could emulate ListView a bit more. Specifically the onFinishedInflate method which adds child layouts as a list of headers. Of course, I could also add an explicit AddHeaderView method that could be called multiple times.

I’ve ignored footers entirely. Again, this is just because I don’t currently have any need for a footer. They could be added easily enough following the same pattern as headers.

Happy Coding.

this post was originally on the MasterDevs Blog

I’ve spent the past few hours working through a fresh install of Xamarin Studio. While most of it is really easy, there are some major gotchas. The best thing about the process is that it is one installer for everything including dependencies. The download page misleadingly asks you what level license you want when. Ignore that. It has nothing to do with the installer or the license you actually wind up using. If you’re just trying it out there’s a 30 day trial license that gets you access to all of the features.

The installer pulls down all of the Android development tools as well: the emulator, the SDK manager, java samples. Everything. After the installer finishes you are ready to write your first android app. Almost.

Hello World in Xamarin Studio

First thing I did was fire up Xamarin Studio (their IDE) and create a new Android Application. Out of the box this is a “Hello World” app with a single button on a page. Couldn’t get much simpler. It didn’t compile for me. I got:

‘Error MSB4018: The “Aapt” task failed unexpectedly’ on new Android Application. No code added.

The solution here was fairly simple. Go to the Android SDK Manager (it should be in your start menu/screen) and install all of the updates. Just click the install button on the bottom right.

Once that’s done you can go back and run your app. It will prompt you to launch an emulator and deploy the app automatically. One thing to note here is that the emulator can take a while (minutes) to start up. Even worse, once it is fully started it stays on the ANDROID loading screen waiting for you to hit a button. There’s no way for you to know it’s ready for you unless you go back and poke it every now and then.

Debugging in Visual Studio

While Xamarin Studio seems to be a decent IDE and you can debug an application from there (breakpoints, watch screens, variable evaluation on mouse hover, threads list, etc.) I am definitely more comfortable with Visual Studio. If you don’t have a trial (or real) license yet, you will be prompted for it when you open up a Xamarin project in Visual Studio, either by opening the solution file you created in Xamarin Studio or by creating a new Android project directly in Visual Studio. That’s where it stops being easy though. The first thing you might notice is that when you try to debug the application you get the following error:

The application could not be started. Ensure that the application has been installed to the target device and has a launchable activity (MainLauncher = true).

Additionally, check Build->Configuration Manager to ensure this project is set to Deploy for this configuration.

The error message is right, the application wasn’t installed on the “target device” (the emulator). If you created the project in Xamarin Studio you need to explicitly tell VS that you want to deploy the app the phone before debugging. Go to the Configuration Manager and ensure that Deploy is checked off for your project.

If you created the project in Visual Studio, you shouldn’t have this problem. it seems to only happen when you create the project in Xamarin Studios first.

Now that the application is deployed to the phone there is still one more hurdle before you can debug from Visual Studio. Whenever I tried to attach to a running virtual machine the debugger would deploy the app and chug along for a little while. Eventually it would quietly die and disconnect. The application wouldn’t load in either the debugger or emulator. I didn’t see anything in the log file that helped point to the problem. Eventually I got lucky and determined that I could connect if the virtual machine was running an Intel Atom (x86) processor then everything worked. My assumption is that Visual Studio doesn’t know how to compile for ARM. If you look at the project properties for an Android app in Visual Studio, there is only x86 and x64:

Xamarin’s site has some pretty easy to follow instructions on how to configure an x86 emulator. The main task is to install Intel’s HAXM software. What they skip over is that you can’t install this if you have Microsoft Hyper-V installed. Hyper-V is Microsoft’s hardware virtualization stack that is used by the Windows Phone Emulator. Ben Armstrong has some really good instructions on how to create a profile in Windows that will disable Hyper-V at startup. They boil down to two commands to run on the command line and a restart:

bcdedit /copy {current} /d "No hypervisor"
bcdedit /set {GUID From the previous command} hypervisorlaunchtype off

For the GUID in the second command, copy the output of the first command including the brackets. It should look something like this: {7d067ad2-16ce-11e2-a059-9b573bf76ddc}. Then just restart the computer and select “No hypervisor” when prompted at the boot screen. From here you can continue through the instructions on how to configure an x86 emulator.

There’s a trade off here. You won’t be able to switch between debugging a Windows Phone application and an Android application without restarting your computer, but on the other hand, because it uses hardware level virtualization, the x86 emulator is significantly faster than the ARM versions.

UPDATE:

After running these two commands a couple of times, I got lazy and wrote a powershell script to do everything in one go:

# This script makes a copy of the current boot record and disables Hyper-V
# The next time the computer is restarted you can elect to run without Hyper-V
  
$output  = invoke-expression 'bcdedit /copy "{current}" /d "Hyper-V Disabled"'
$output -match '{.*}'
$guid = $matches[0]
$hyperVCommand = 'bcdedit /set "' + $guid + '" hypervisorlaunchtype off'
invoke-expression $hyperVCommand

Summary

Here’s a quick run down of the steps covered above

  1. Download and install Xamarin Studio
  2. Install all the updates in the Android SDK Manager
  3. Make sure Visual Studio knows to deploy the app before trying to debug
  4. Disable Hyper-V
  5. Configure an x86 emulator

this post was originally on the MasterDevs Blog

Trying to debug a new Windows Phone 8 application today I came across this problem. Whenever I hit F5, the emulator would start up like normal but Visual Studio would prompt me with a message box saying:

A specified communication resource (port) is already in use by another application.

Then the debugger would fail to start. After trying all of the obvious options and restarting everything in sight, I stumbled across a bit of advice which worked for me. Right click on your project and select Deploy. This will copy all necessary code to the emulator. After that you are free to hit F5 like normal.

this post was originally on the MasterDevs Blog

Windows Phone 8 comments edit

The Windows Phone 8 emulator depends on Hyper-V in order to run. The problem is that the consumer edition of Windows 8 doesn’t support Hyper-V. The easiest way I found to install it was to upgrade to Windows 8 Pro. Luckily with Windows 8 upgrading does not mean reinstalling. You can simply enter a new license key and you’re off to the races.

Now, none of this was obvious at least to me. Before figuring all this out I spent some time Googling and Binging. Hopefully you can use some of the information I gathered.

The first sign of trouble was when I installed the Windows Phone 8 SDK. If you don’t already have Hyper-V, you will see a cryptic warning that the SDK installer was not able to add you to the Hyper-V Administrators group.

Assuming this to be an important warning, I attempted to add myself the old fashioned way, through the Local Users and Groups snap-in. As it turns out though, that snap-in is not available on the standard edition of Windows 8. This should have been my first clue that something was amiss. Sadly, I didn’t pick up on it this early in the game.

Seeing myself at a bit of a dead end, I decided to move on and hope for the best. I opened up an existing Windows Phone 8 project in Visual Studio and hit debug. The next error message shed a light on why I couldn’t be added to the Hyper-V Administrators group; I didn’t have Hyper-V installed. It linked me to a somewhat useful MSDN article on the emulator’s requirements.

This article does a good job of explaining how to enable Hyper-V in your BIOS as well as Windows itself. It even tells you how to determine if your hardware can support Hyper-V. Not to repeat the article too much, but you can download Sysinternals’ Coreinfo tool and run it on the command line. Passing it the -v parameter will help minimize the noise in the output to just the fields you’re looking for. V stands for virtualization.

Now that I had verified that it wasn’t my hardware it was time to start looking at the software. To check what Windows features installed and/or disabled go to Programs and Features through the control panel and clicking on the “Turn Windows features on or off” link on the left hand side. Or even easier, bring up the search charm and type in “Turn Windows features on or off”. As you can see below, I didn’t have Hyper-V in my feature list.

To figure out how to get it installed, I started looking at my OS. I checked out Wikipedia to see what the different editions of Windows 8 were. Had I been smart enough to actually read the feature list at the bottom or the 3 sentence description of the editions, I would have seen that Hyper-V is only available in the 64 bit Pro and Enterprise editions. As it was, knowing that the official name of the consumer edition was simply (and confusingly) “Windows 8” was enough to verify which version of the OS came installed on my machine.

I already had an available Pro product key, so my next step was to try to upgrade as as painlessly as possible. As it turns out that was the easy part. To do this go the share charm and type in “add features to Windows 8”. You should see one option under settings. This will let you either buy a key or enter an existing one.

After you click next your Windows installation will upgrade itself which does take some time and a reboot. Now when we come back to the Turn Windows features on or off dialog Hyper-V is available but unchecked.

Simply check it off, click OK and wait for some more installation and reboots to happen.

Now I was finally able to go back to Visual Studio and hit debug again. I did miss one thing however. I still wasn’t in the Hyper-V Admin group. The emulator is smart enough to recognize that and offer to automatically fix it. Clicking OK on the prompt was enough to finish all the configuration I needed and finally show me my app:

this post was originally on the MasterDevs Blog