Statically Defining Tabs on a Xamarin.Forms TabbedPage

In Xamarin.Forms screens are represented by Pages – a Page is a View Controller in iOS, an Activity in Android, and well.. a Page in Windows Phone.

One of the Page types that come with the Xamarin.Forms toolkit is TabbedPage which allows you to place tabs on the screen in a platform specific manner – so on the bottom bar in iOS, along the top in Android and as a pivot control in Windows Phone. The TabbedPage is a MultiPage<Page> so it is made up of a collection of Page objects, or subpages, which represent the content of the tabs.

There are a couple of ways of defining the child Pages (i.e., tabs) of a TabbedPage – you can set its ItemsSource which will give you a dynamic set of tabs based on a collection of items which you then define an ItemTemplate for, or you can simply set the tabs statically.

There are a couple good examples of how to accomplish the ItemsSource/binding approach both in the API documentation and in the TabbedPageDemo in the Xamarin.Forms Sample GitHub repo. The “static” approach isn’t specifically called out in the samples, but you can actually find an example of how to accomplish it in the MobileCRM sample.

I think it’s typically more common to set tabs on a mobile app up based on a couple of known items (which more than likely will have different content layouts) rather than a databound collection of items. So I thought I would specifically call out how this can be accomplished with a couple quick samples.

In XAML:

[gist https://gist.github.com/edsnider/e1dd04b58c4eaae1d2eb file=”StaticTabs.xaml”]

In C#:

[gist https://gist.github.com/edsnider/e1dd04b58c4eaae1d2eb file=”StaticTabs2.cs”]

Or, just add other Pages directly:

[gist https://gist.github.com/edsnider/e1dd04b58c4eaae1d2eb file=”StaticTabs3.cs”]

Making Professional Mobile Screenshots

As a mobile app developer you may often find yourself needing to display screenshots of your work – perhaps for documentation, a slide deck, app store submission, or even a proposal or some other marketing asset. Getting a screenshot of your app is pretty trivial – you can capture it from the device itself or within the various emulators. However, the screenshot is going to look rather plain and typically sans device frame (e.g., just the screen itself, no skin). There are several web-based resources you can leverage to take those screenshots from plain to professional without even opening Photoshop:

Before

Before (plain)

After (professional)

After (professional)

  1. placeit (https://placeit.net) – I find this resource most useful for building slides because it not only provides an actual device to frame your screenshot in but it also offers several environment scene options to help bring your app to life.  I like to use these graphics as full-bleed backgrounds on slides for a rich, modern look-and-feel.  They offer ‘stages’ for iPhone, iPad, various Android devices, and even the Microsoft Surface. Note: You’ll have to pay for the larger images but it’s definitely worth it)
  2. mockUphone (http://mockuphone.com) – This resource offers iOS, Android and Windows Phone frames with transparent backgrounds allowing you to place them anywhere for a seamless look. In addition to portrait and landscape, several of the iOS and Android options also include angled views as well.
  3. iPhone Screenshot Maker (http://iphone-screenshot.com) – Despite its name, this resource offers several iOS device frames as well as a couple for Android (and for the older Windows Phone 7).

Depending on your needs you may be able to get away with just using one of these resources or a combination of them – either way hopefully this will help you quickly produce professional looking screenshots for all the mobile platforms your app is on.

Clearing Windows Phone Nav Back Stack in MvvmCross

There are often times when you might need to clear the navigation stack (aka back stack) in an app.  One common example of this is when you allow a user to sign out – you don’t want them to be able to tap back and still have the ability to see the previous views.  As you can image, this is done differently on each platform and therefore it can’t be done directly from a ViewModel – but there is a way to control it from the ViewModel.

In MvvmCross you can create “Presentation Hints” that can be passed to the UI/view directly from a ViewModel.  Presentation Hints are handled by a ViewPresenter and since ViewPresenters live in the view layer and are platform specific you can detect the hints passed from the ViewModels and handle them in platform specific ways.

So in the case of clearing the back stack you can create a “ClearBackStackPresentationHint” in your PCL which really has no implementation and then pass a new instance of it into the ChangePresentation() method which you get when you inherit from MvxViewModel.

Then, to handle the hint you need to make a custom ViewPresenter inheriting from the platform specific version of IMvxViewPresenter (e.g., inherit from MvxPhoneViewPresenter for Windows Phone, MvxAndroidViewPresenter for Android, or MvxTouchViewPresenter for iOS).  Finally, you need to register your custom ViewPresenter so it is used over the default one.  You do this in the CreateViewPresenter() method of your Setup class.

Here is how to do it for Windows Phone:

And then from your ViewModel you can do this and the back stack will be cleared:

ChangePresenation(new ClearNavBackStackHint());

Since the Show() method gets called before the ChangePresentation() method in the ViewPresenter you have to be careful the order in which you call the ChangePresnetation() method in your ViewModel. If you call it before you call the ShowViewModel<>() method (in a situation where you want to leave the current view and clear the stack) you will end up with that last view still on the stack.  To fix this simply call the ChangePresentation() method after calling the ShowViewModel<>() method.  Taking this a step further I typically add a ShowViewModelAndClearBackStack<>() method to my BaseViewModel class so it can be handled in one place and you know the order is always consistent.

Now, from your ViewModel just call ShowViewModelAndClearBackStack<>() and the user will be taken to the view with no way of going back (other than to exit the app).

ShowViewModelAndClearBackStack<WhateverViewModel>();

Toggling Windows Phone App Bar Visibility

Quick note on changing the visibility of an app bar in a Windows Phone app.

Toggling the visibility of a page’s app bar from code-behind is slightly different than most other controls.  Unlike other UI elements, the visibility of the app bar on a page should note be set using the app bar’s name – this could result in null reference exceptions when the app bar’s visibility is set to false.  Instead (and actually a bit more straightforward) the app bar’s visibility should be set using the page’s ApplicationBar property:

ApplicationBar.IsVisible = false;

Setting up the Moto G for Xamarin.Android Dev

The ability to build native apps for multiple platforms with Xamarin is pretty awesome.  But developing apps for multiple platforms means you might “need” to get some new toys (not a bad thing if you’re like me :)).  Personally I use a Windows Phone – I love the platform and have been on it since it came out.  I have tons of WP devices lying around the house but not a single Android device (or iOS actually) – so I’ve simply been using Android emulators to do Xamarin.Android development.  Unfortunately, the emulators are horribly slow… you even get a message warning you about it:

emulatorerror

The Genymotion emulators are a pretty good alternative and James Montemagno has a great post on getting the x86 Android emulators working but it’s always nice to be able to debug and test on an actual device so I went ahead and purchased one.

The Motorola Moto G

I didn’t want to add a new line to my mobile plan so I picked up one of the “pay-as-you-go” no-contract Verizon phones – the Motorola Moto G.  Normally these types of phones are lower end devices but the Moto G is actually a decent piece of hardware and it was only $99.  It comes running Jelly Bean (4.3) and can be upgraded to KitKat (4.4).

When you fire the Moto G up for the first time it will ask you “activate” it and tries to get you to setup a monthly plan.  At first it almost seems like you can’t get around this, but you can.

Setting the Moto G up for development

Turn on USB debugging

In order to use the Moto G for testing apps you need to turn on USB debugging in Settings > Developer options.  Note: The Developer options are is hidden by default so if this is the first time you’re using the Moto G for development you’ll need to reveal them.  To do this simply go to Settings > About phone and find the Build number (all the way at the bottom) – tap the Build number item several times and the Developer options will be magically enabled.

Install USB drivers

When you first plug your Moto G into your Windows machine via USB you’ll notice the device is accessible through Windows Explorer but there are no drivers installed for the device when you view it in Device Manager:

devicemanager-nodrivers

The Google USB Driver that can be downloaded/installed via the Android SDK Manager will not work for the Moto G.  Instead, you need to get the drivers directly from Motorola by downloading and installing the Motorola Device Manager for Windows (there is a version for Mac OS X as well, although you shouldn’t need the drivers on the Mac).

Once you download and install the Motorola Device Manager you should be able to jump back into the Device Manager (Win+R; devmgmt.msc) and see that the device is now listed under Android Device and is has drivers properly installed:

devicemanager-withdrivers

You will also notice an alert on your Moto G device asking you to allow USB debugging:

motog-allowdebugging

After you tap OK you will find the Moto G (Motorola XT1028) listed in Target Android Device drop-down in Visual Studio:

vs2013targetandroiddevices

You can also find the Moto G (Motorola XT1028) listed in the Select Device dialog when you Start Debugging and in the Run With menu in Xamarin Studio:

xs-selectdevicedialog

xs-runwithmenu

You should now be all setup to use the Moto G in your Xamarin.Android development!

Tip: Use Windows Libraries for quick access to SharePoint server files

As a SharePoint developer or server admin you’ll find yourself in and out of the 14 hive all day long.  You also make frequent trips to the various web app virtual directory folders.  Both of these key locations are fairly deep and it can get rather annoying traversing down into them.  So I started taking advantage of the Library feature that comes with Windows Server 2008 (and Windows 7, of course) to make it easier to access the files in these locations.

As you can see in the screenshot below I’ve setup a couple Libraries.  I setup a 14 Hive Library that basically just gives me a quick link right to the 14 folder.  I also setup a SP Virtual Directories Library in which I’ve included each of the web application root folders.  So now with only one click I can access all of my web.config files and bin directories in a single location – pretty handy.  “Windows 7 was my idea!”

How to Predefine SPGridView FilterExpression

There are many situations where you might need to predefine or set a default FilterExpression for a SPGridView control.  This would be a situation where you want to filter the rows within a SPGridView prior to the user selecting any filter parameters from the column headers.  I find this particularly useful when initial grid filtering should be based on a selection made from a connected web part such as in a drilldown scenario.

The filter settings including data fields to be filtered and the format of the FilterExpression that are applied to the SPGridView in the CreateChildControls method aren’t actually applied to the data source until the user actually selects a filter from the column header.  This means you can’t temporarily modify the FilteredDataSourcePropertyFormat property on the grid view prior to the initial DataBind call because the FilterExpression won’t be used by the data source at this point.  So, in order to have the data source perform a filter you need to set the FilterExpression on the data source object itself prior to DataBind call in the OnPreRender method.   You’ll see what I mean in the code below.

So by doing this you now have the SPGridView filtered by default without the user selecting the filter from the column header.  But now that you’ve defined the FilterExpression on the data source it will override any user selected filters since they applied prior to the OnPreRender call.  The way around this is to simply check if the read only fields FilterFieldName and FilterFieldValue are defined.  If they are then the user has specified a filter and you want the data source to use it as opposed to the predefined expression.

Here is some sample code to illustrate my point (assume the two string variables represent values defined by another web part or source external to the grid view):

private SPGridView _spgv;
private ObjectDataSource _ods;

private string defaultFilterColumn;
private string defaultFilterValue;

protected override void OnPreRender(EventArgs e)
{
	base.OnPreRender(e);

	// ...
	// code to create grid view columns would be here...
	// ...

	if (string.IsNullOrEmpty(_spgv.FilterFieldName) && 
	    string.IsNullOrEmpty(_spgv.FilterFieldValue))
	{
		_ods.FilterExpression = string.Format(_spgv.FilteredDataSourcePropertyFormat, defaultFilterValue, defaultFilterColumn);
	}

	_spgv.DataBind();
}

protected override void CreateChildControls()
{
	base.CreateChildControls();

	// ... 
	// code to define and setup ObjectDataSource
	// ...

	_spgv = new SPGridView();
	_spgv.AllowFiltering = true;
	_spgv.FilterDataFields = "ColumnOne,,ColumnThree,";
	_spgv.FilteredDataSourcePropertyName = "FilterExpression";
	_spgv.FilteredDataSourcePropertyFormat = "{1} = '{0}'";

	this.Controls.Add(_spgv);
}

This configuration will let you to apply a filter to the SPGridView data on load and then allow users to change it by specifying their filter criteria from the column header filter menus within the SPGridView control.

Some notes:

  • If the user selects “Clear Filter from …” on the filter menu the SPGridView will return to the state at which it was filtered using the predefined FilterExpression.  This may not be an issue – just depends on the use case really.  If you want the Clear Filter command to completely clear the filter, including the predefined filter, then I would recommend setting a boolean variable with some logic to ignore the default filter information and set the data source FilterExpression to empty.  You can catch the Clear Filter click in the LoadViewState method some like below: 
    protected sealed override void LoadViewState(object savedState)
    {
    	base.LoadViewState(savedState);
    
            if (Context.Request.Form["__EVENTARGUMENT"] != null &&
                Context.Request.Form["__EVENTARGUMENT"].EndsWith("__ClearFilter__"))
    	{
    		_ignoreDefaultFilter = true;
    	}
    }
    
  • Also, because you are setting the initial filter directly on the data source and not via the SPGridView filter properties the column header filter menu will not reflect the predefined filter being applied (only the user selected filter).  There is probably a simple way around this, I just haven’t messed with it yet.