The Xamarin Project Mystery

In this post I will try to clear up some missconceptions about the Xamarin Forms project structure, have a closer look at the differences between PCL and Shared Projects and explain some tricks that you can do with both of them.

First there was confusion

I recall when I started with Xamarin the wizard created solution looked pretty alien to me. At this time I started with a PCL based solution because that’s what was recommended everywhere. We’ll have closer look ate this later in this post

pcl_project_structure

There was a (portable) subproject and one with .Android and one with .iOS extension. After reading some docs I understood that the PCL part is a platform independent library and in the other two are the platform specific code. Still I did not understand how are these projects connected to each other. I got further confused reading that I cannot call any platform specific code from the PCL project unless I use the Xamarin Dependency Service

This left the feeling that there must be some black magic going on under the hood that brings all together which left me a bit uncomfortable but it seemed to work somehow.

No Magic in here

The most confusing part was that all my Apps important code like the App class and all my pages were in the PCL project. So I thought that’s the project that will generate the final App and that the other two just get linked somehow.

What I did learn while already happy coding was that the .Android and .iOS projects are the so called Platform Projects which will result in our final App when compiled and linked. This projects will just link in the PCL part which just a dll, that’s all to it. So in reality it was exaclty the oposite that I first thought.

PCL_project_schema

This has some interesting consequences. Although code in the PCL cannot access code inside the platform projects the other way round is indeed possible.

This suddenly also explained how the DependencyService could work. It’s code is located in the Xamarin Forms (XF) library which is a PCL itself and which is referenced from our PCL project and from the Platform Project which makes it possible for the Platform Project to register instances of platform dependent classes inside the XF code which then can be retrieved via it’s platform independent interface from inside our PCL project.

We don’t need magical attributes and Services

to access platform specific code. All it takes is a static property in a class in our PCL project and a platform independent interface like

public interface IFileStorage
{       
    string ReadAsString(string filename);
    byte[] ReadAsBytes(string filename);
}

In each of the Platform projects we implement this interface with a platform specific implementation.

Android:

namespace XamarinSampleSolutionPCL.Droid
{
    public class FileStorage : IFileStorage
    {
        public string ReadAsString(string filename)
        {
            var bytes = ReadAsBytes(filename);
            return Encoding.UTF8.GetString(bytes);
        }

        public byte[] ReadAsBytes(string filename)
        {
            AssetManager assets = Android.App.Application.Context.Assets;
            using (Stream stream = assets.Open(filename))
            {
                using (var memStream = new MemoryStream())
                {
                    stream.CopyTo(memStream);
                    return memStream.ToArray();
                }
            }
        }

    }
}

iOS

namespace XamarinSampleSolutionPCL.iOS
{
    public class FileStorage : IFileStorage
    {
        public byte[] ReadAsBytes(string filename)
        {
            var data = File.ReadAllBytes(filename);

            return data;
        }

        public string ReadAsString(string filename)
        {
            var data = ReadAsBytes(filename);

            if (data == null)
                return string.Empty;

            return System.Text.Encoding.UTF8.GetString(data);
        }

    }
}

In our App class in the PCL Project I added a static property:

namespace XamarinSampleSolutionPCL
{
    public partial class App : Application
    {
        public static IFileStorage FileStorage;

To make everything working together we have to create an instance of the platform specific classes and assign it to this static property and we can use it inside the PCL over this static property.

Here is the example how to do it in Android:

protected override void OnCreate(Bundle bundle)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;

    base.OnCreate(bundle);

    global::Xamarin.Forms.Forms.Init(this, bundle);

>>  App.FileStorage = new FileStorage(); // Thats the interesting line

    LoadApplication(new App());
}

I don’t say that this is an optimal solution! But it should give you a better understanding of how this projects play together. Using a ServiceLocator like the XF DependencyService has the advantage that your PCL code does not use a static property of any of your classes and you can access the instance from anywhere in your code. If you want to use a ServiceLocator I personally prefer Splat which gives you much better control and does work without magical class attributes.

What are these other files for?

This might seem trivial for some of you but from my experiences in the Xamarin Slack not everyone knows. Stay tuned we will get more interesting stuff in a minute.

  • package.config: nuget packages that you add to your project are stored in here. But don’t think you can just edit it to add or remove packets because they are also referenced in your .csproj files. So always use the nuget Manager or the console

In the PCL

  • App.xaml and App.xaml.cs: if you have read my previous post (if not do it now) you know that the combination of .xaml and .xaml.cs just creates a class. In this case your Appclass which has the responsibility to create your first page in it’s constructor. Although it has a .xaml part this is not a page. In the .xaml part you can define global styles and the like. If I don’t need the xaml part I often replace this combination with a simple App.cs class like
public class App : Application
{
    public static IFileStorage FileStorage;

    public App()
    {
        InitializeComponent();

        MainPage = new XamarinSampleSolutionPCL.MainPage();
    }

    protected override void OnStart()
    {
        // Handle when your app starts
    }

    protected override void OnSleep()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume()
    {
        // Handle when your app resumes
    }
}

In the Android project:

  • MainActivity.cs: OnCreateis the first method that is called when your App starts up. So all platform specific initialization should go there.

In the iOS project:

  • AppDelegate.cs: here FinishedLaunchingis the first Method to get called when our App starts up.

Shared Projects, the black sheep of the family

If you ask in the community which one of the two you should choose you almost for certainly will hear Shared Projects are bad which actually almost got to some sort of dogma.

But first what are Shared Projects anyway? So lets have a look what the structure of a shared project looks like:

shared_project_structure

Looks pretty similar but what’s that strange symbol:

shared_part_symbol

This is actually a pseudo project which means it’s not a real project at all but a trick of Visual Studio (That’s the reason why you cannot add a nuget to it).

All files that you add to this “project” will be added to all platform projects at the same time by using file links.

shared_project_shema

I left out the link step intentionally

So if all files get compiled to the same binary this means that all files could access platform specific code. But to be able to compile the files in the shared part in both platform projects they should not do that because what knows an iOS compiler about Android APIs.

The idea is that you only put classes in the shared part that don’t use any platform specific code.

But (and here comes the critique of the people that think shared projects are bad) you can use #if __ANDROID__ and #if __IOS__ in the shared part to still use platform dependent code which makes a mess of your code and is bad style.

That you can do this does not means you have to or you should do and doesn’t make Shared Projects bad. Although it somehow comforts me to know that I have this possibility as last resort 🙂 .

As long as you follow this rule there is really nothing bad about Shared Projects and fact is the core App code will seldom reused in another project.

Put all code you want to reuse somewhere else in a separate PCL project and reference that from the Platform Projects and you are fine.

Advantages of Shared Projects

If you ever used a PCL project you will earlier or later have encountered the moment where a nuget that you want to use does not match the PCL profile of your PCL project which is pretty annoying especially because you cannot change your PCL profile without uninstalling all nugets first. Even worse as more and mode nugets are migrated to netstandardthe successor to PCL you will get more conflicts.

A shared project can consume any nuget independent from it’s PCL profile. So for now I actually recommend Shared Projects if you start a new one. This might change when netstandard tooling gets more mature and with the release of netstandard 2.0.

Accessing Platform code from the shared part of Shared Project

As we should not use #if what else can we do. Actually you have two possibilities.

  1. You still can use a ServiceLocator like Splat and register your platform specific interface implementations in the Platform project classes and access them via the interface and the Locator in the Shared part.

  2. You can use partial classes what someone called the poor man’s bait and switch. This makes especially sense if the class contains platform independent and dependent code.

Let’s implement the same service as in the PCL Solution in the Shared project:

In the Shared Part we add a file named FileStorage.cs

    public partial class FileStorage
    {

        // This is a stupid example for a platform independent method
        string ReadUpperString(string filename)
        {
            return ReadAsString(filename).ToUpper();
        }

        string ReadAsString(string filename)
        {
            return ReadAsStringImplementation(filename);
        }

        byte[] ReadAsBytes(string filename)
        {
            return ReadAsBytesImplementation(filename);
        }

    }

In the Android Part we add a file named FileStorage.Android.cs

Please note that we cannot use the same file name

public partial class FileStorage 
{
    public string ReadAsStringImplementation(string filename)
    {
        var bytes = ReadAsBytes(filename);
        return Encoding.UTF8.GetString(bytes);
    }

    public byte[] ReadAsBytesImplementation(string filename)
    {
        AssetManager assets = Android.App.Application.Context.Assets;
        using (Stream stream = assets.Open(filename))
        {
            using (var memStream = new MemoryStream())
            {
                stream.CopyTo(memStream);
                return memStream.ToArray();
            }
        }
    }

}

This part can fully access the Android APIs

And in iOS:

public partial class FileStorage
{
    public byte[] ReadAsBytesImplementation(string filename)
    {
        var data = File.ReadAllBytes(filename);

        return data;
    }

    public string ReadAsStringImplementation(string filename)
    {
        var data = ReadAsBytes(filename);

        if (data == null)
            return string.Empty;

        return System.Text.Encoding.UTF8.GetString(data);
    }

Our Solution now looks like this:

shared_project_structure_partial_class

You can find both solutions on my Github Repository:

PCL Solution

Shared Solution

The secret life of a Xaml Page

Disclaimer: Post describes Xaml Pages used in Xamarin Forms

If you are like me the first time when confronted with a Xaml page they look sort of really alien to an old school programmer who has never did dirty web stuff before.
After reading some articles about using them you finally grasp what you can do with them but still there is a sort of magic around them or at least if feels like a strange sort of animal that you have learned how to ride following all the examples but still you are not really sure what it really is and how does it work and if you can trust it.

Xaml Pages are just classes

OK not completely true but at least partial (pun intended). They are one part of a page class, the other one is normally declared in your xxx.xaml.cs file. Visual Studio only knows that they belong together and displays them linked together so that they look like some special thing.

If you have a Xaml Page like

<?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="FormsTest.Pages.BasicPage">
  <Label Text="Hello Forms" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

with it’s counterpart

using Xamarin.Forms;

namespace FormsTest.Pages
{
    public partial class BasicPage : ContentPage
    {
        public BasicPage()
        {
            InitializeComponent();
        }
    }
}

it is basiscally the same as if you write in code:

class BasicCodePage : ContentPage
{
    public BasicCodePage()
    {
        Content = new Label() {Text = "Hello Forms", HorizontalOptions = LayoutOptions.Center,
                                VerticalOptions = LayoutOptions.Center};
    }
}

The most important part in the Xaml header x:Class="FormsTest.Pages.BasicPage" tells the compiler to which partial c# class this Xaml belongs.

The magical part

How does this work? Basically your Xaml definitions get included in your assembly as embedded resource. When creating an instance of the page Forms parses the Xaml and instantiates the there defined classes like <Label>, <Grid>, <ScrollView> any set attributes get assigned to the same named properties of this classes.

You can see it yourself checking the objfolder of you project where you find temporary generated files of your pages like:

    public partial class BasicPage : global::Xamarin.Forms.ContentPage {

        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private void InitializeComponent() {
            this.LoadFromXaml(typeof(BasicPage));
        }
    }

InitializeComponent();

If you look at the constructor of the partial class you find a generated call of InitializeComponent. This call instantiates and initializes all of the objects defined in the XAML file, connects them together in parent-child relationships, attaches event handlers defined in code to events set in the Xaml file, and sets the resultant tree of objects as the content of the page.
Taking this into account it now get’s clear why you NEVER EVER SHOULD TRY TO ACCESS ANY CONTROL of your page before this call because they just don’t exist at this point and you will get an exception.

Quite often you will get compiler errors that tells you that InitializeComponentdoes not exist. Looking at your partial C# class we have to admit that indeed there is no such method. So it must be defined somewhere in the from Forms generated second half of our page class. So if you get this kind of error in most cases the link between the code-behind file (how your partial class is often been called) and the Xaml definition is broken. You first stop is therefore checking the x:classdefinition in your Xaml header if the name there matches the class name of your c# class.
Another reason can be that VS or XS did not set the correct build tool for the Xaml page. Checking the Xaml files properties Custom Tool should be set to MSBuild:UpdateDesignTimeXaml and Build Action to `Embedded Resource.

Named Controls

In a lot of tutorials you see that the code is accessing the controls of the page just by there name which was set with the x:name attribute on the Xaml control.

<?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:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.BasicPage">

  <Label x:Name="MyLabel" Text="Hello Forms" VerticalOptions="Start" HorizontalOptions="Center" />
</ContentPage>

How does this work? The answer is that the Xamarin compiler will create a field for every named element in your Xaml definition inside your Page class. This is the code the compiler generates for the Xaml page:

    public partial class BasicPage : global::Xamarin.Forms.ContentPage {

        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private global::Xamarin.Forms.Label MyLabel;

        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private void InitializeComponent() {
            this.LoadFromXaml(typeof(BasicPage));
            MyLabel = this.FindByName<global::Xamarin.Forms.Label>("MyLabel");
        }
    }

If you want to dig deeper into this please check out: Anatomy_of_a_XAML_Class

Custom Controls

Recalling that

<?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="FormsTest.Pages.BasicPage">
  <Label Text="Hello Forms" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

The <Label> directive instantiates an Object of the class Label you could get the idea if it would be possible to use any class inside Xaml. And actually you can. Ok, not any class everywhere but you can use any from `VisualElement derived class as controls. So if you need a custom controls, you can just derive your class from an existing control and use it on your page.

E.g. if we want to have an control that capitalizes every input we could do this like so:

class CapitalEntry : Entry
{
    public CapitalEntry()
    {
        TextChanged += CapitalEntry_TextChanged;   
    }

    private void CapitalEntry_TextChanged(object sender, TextChangedEventArgs e)
    {
        Text =   e.NewTextValue.ToUpper();
    }
}

This might be a pretty naive solution but works for this example.

and use it in our Page just 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"
             xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.BasicPage">
  <StackLayout>

    <Label Text="Hello Forms" VerticalOptions="Start" HorizontalOptions="Center" />

    <pages:CapitalEntry VerticalOptions= "Start"/>

  </StackLayout>
</ContentPage>

The only thing to be able to use our own classes is to tell forms in which assembly they are to find. That’s why we need this line

 xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"

It defines Xaml namespace so that we now can reference classes from external assemblies. You only need “assembly=XXXX” if the control is in a different assembly to the page you’re referencing it from.

This also means that you can easily reuse parts of your page by defining them as separate classes and use that in your pages.
When doing this and define your “page parts” as ContentView or ViewCell derived classes you can define them in Xaml too and get even more flexibility because you can let it handle their own events in their own code-behind files to create more complex self contained custom controls.

Now I moved the content of the previous Page to a custom View class:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.PagePartView">
  <ContentView.Content>
    <StackLayout>

      <Label Text="Hello Forms" VerticalOptions="Start" HorizontalOptions="Center" />

      <pages:CapitalEntry x:Name="capitalEntry" VerticalOptions= "Start" TextChanged="Entry_OnTextChanged"/>

    </StackLayout> 
  </ContentView.Content>
</ContentView>

with it’s own code-behind file:

namespace FormsTest.Pages
{
    public partial class PagePartView : ContentView
    {
        public int MaxLength { get; set; } //Will be accessible as Xaml Attribute

        public PagePartView()
        {
            InitializeComponent();
        }

        //Limit the entry to MaxLength characters 
        private void Entry_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            if (e.NewTextValue.Length > MaxLength)
                capitalEntry.Text = e.OldTextValue;
        }
    }
}

Then we can use it in our page:

<?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:pages="clr-namespace:FormsTest.Pages;assembly=FormsTest"
             x:Class="FormsTest.Pages.BasicPage">

  <pages:PagePartView MaxLength="10"/>

</ContentPage>

As you see we can pass values to properties of our custom view as Xaml attributes.

Deriving Pages

You can derive Pages but with some limitations.

  • It’s possible to derive a Xaml Page from a Page defined in code that does not create any controls but only provides other functionality.
  • You can derive a code defined Page from a Xaml defined page that can access the Xaml defined controls of it’s parent page.
  • You cannot derive a Xaml defined Page from another Xaml defined page (unless they only define resources and no content)

If you want to derive a Xaml page from some outside defined base page the definition looks a bit strange as you have to use the base classes namespace before it is even declared:

Here an example that derives from ReactiveContentPage defines in the ReactiveUI library package.

<?xml version="1.0" encoding="utf-8" ?>
<rxui:ReactiveContentPage x:TypeArguments="pageModels:SettingsFilerPageModel" xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:rxui="clr-namespace:ReactiveUI.XamForms;assembly=ReactiveUI.XamForms"
             xmlns:pageModels="clr-namespace:FormsTest.PageModels;assembly=FormsTest"
             x:Class="FormsTest.SettingsFilterPage" BackgroundColor="Black">

This example is even more interesting because it shows that it’s possible to derive a Xaml Page from a generic base class. The generic type parameter is passed by using the x:TypeArgumentsdeclaration.

Why can’t I bind my Xaml Controls to Properties of my Page class?

A lot of developers when starting using MVVM as design principle try to bind attributes or command of their controls in the Xaml definition to properties defined in the code-behind file of the page and are surprised that this doesn’t work.

Besides that it makes no sense at all to bind to elements of your code-behind file, the reason is that the {Binding}
markup extension tries to make link between the Attribute it is set with an object assigned to the BindingContextproperty of the Page class and not to the Page itself.
Now you could get the idea and assign this.BindingContext = this inside the constructor of the page, but it really makes no sense if you recall that the compiler fuses the Xaml Definition together with the code-behind file to one single class. Binding inside one class does not make any sense at all.
If you want want access your pages controls just give them names with the x:name attribute and access them directly. And if you want to handle events in the code behind, don’t try to use commands, just use the Xaml exposed events.

Should I use the code-behind file at all?

Many MVVM purists will tell you that your code-behind files should only contain the InitializeComponentcall and nothing else.
I’m not that dogmatic. Actually if you are not using the Xamarin Forms bindings you might need to define bindings manually inside the constructor.
Second if we are talking about custom views it might not make sense to bind that to a ViewModel if it acts as a self-contained control. Think of a complex DateView that only exposes a property selected date but handles user interaction inside. This could be completly handled in the code-behind file. Another example is if you have to change some components dimensions based on the physical screen size. It makes much more sense to do this after the ‘InitializeComponent` call in the pages constructor than with a binding from the ViewModel because screen dimensions are something inherently connected to the View and not to the ViewModel.
As so often the answer is it depends 🙂

XamlCompile

You have seen before that Xaml pages are added as Resources and parsed at runtime, so many of you might have thought if this isn’t a bit slow. And indeed it is. Luckily there is a way out of it you can tell Xamarin to compile your Xaml classes directly into IL by simply setting an attribute on your class or on your whole assembly. As I don’t want to just copy the offical documentation, you can find here how to use Xaml Compilation

Advanced ListView Bindings

The traditional Binding

When first making contact with ListViews in an Xamarin Forms MVVM design you usually publish an ObservableCollection as a property of the ViewModel of your Page, bind the ItemSource of the ListView to it and then bind to the items in´the collection in your Datatemplate. Like this:

    [ImplementPropertyChanged]  //I use Fody here to not have to bother with INotifyPropertyChanged
    public class DemoListViewPageModel
    {
        public ObservableCollection<Dog> DogList

        public DemoListViewPageModel()
        {
            DogList = new ObservableCollection<Dog>();

            DogList.Add(new Dog() { Name = "Rex", Race = "German Sheppard" });
            DogList.Add(new Dog() { Name = "Barney", Race = "Poodle" });
            DogList.Add(new Dog() { Name = "Jimmy", Race = "Beagle" });
            DogList.Add(new Dog() { Name = "Rob", Race = "Labrador" });
        }
    }

    // Should be something that makes a bit of sense, so why not dogs
    [ImplementPropertyChanged]
    public class Dogs
    {
        public string Name {get; set}

        public string Race {get; set;}
    }

And in the Page then

<?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="Examples.DemoListViewPage">
  <ContentPage.Content>
    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
      <ListView ItemsSource="{Binding DogList}" HasUnevenRows="True">
        <ListView.ItemTemplate>
          <DataTemplate>         
            <ViewCell>
              <StackLayout HorizontalOptions="Start" >
                <Label x:Name="Name"  Text="{Binding Name}"  TextColor="Navy" FontSize="20"/>
                <Label x:Name="Race" Text="{Binding Race}"/>
              </StackLayout>
            </ViewCell>           
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

That’s fine but

  • It violates MVVM in exposing the model behind it because the DataTemplate binds to model objects
  • The moment we want to store additional data for each item or execute a command from an ViewCell it get’s difficult

While the first might seem be an academic reason it really couples the model tightly to the view which makes changes in the model layer propagate to the view.

Let me elaborate on the second drawback.

  • Imagine we add a check mark (let’s asume we have such a control) to the ViewCell. Now we have to keep track of it’s state somewhere. We could bind its Toggle command to a Command in our ViewModel and also add a List<bool> checkedItems where we store the state for each item in the ListView.
  • We want to add a Add to Shopping Cart Button to our ViewCell. Again we could bind all Buttons of the ListView to a Command in our ViewModel that calls a WebService to add the item to the shopping cart. (Ok this example might be somewhat contrived)

Both both enhancements need additional code in the ViewModel to figure out which item the Command should be exceuted on which should not be the job of the ViewModel. The real reason for the problem is that our ViewModel is the ViewModel for the whole Page. The ListView is a container that holds a list of ItemViews that are defined in the DataTemplateof the ListView. So the consequence should be: Give each ItemView its own ViewModel. Which means our page’s ViewModel no longer exposes a ObservableColletion<Dogs> but ObservableColletion<DogsItemViewModel>

Introducing ViewModels for each ListView item

public class DogsItemViewModel
{
    private Dog DogObject;
    ICommand AddToCartCommand;

    public DogsItemViewModel(Dog theDog)
    {
        DogObject = theDog;
        AddToCartCommand = new Xamarin.Forms.Command(AddToCart);
    }

    public string Name => DogObject.Name;
    public string Race => DogObject.Race.ToUpper();
    public bool IsChecked { get; set; }

    void AddToCart()
    {
        WebService.Instance.AddToCart(DogObject);  // Whatever this will do ;-) 
    }
}

Now the DogsItemViewModel can handle all interaction with the ItemView on it’s own. You can even do conversions on the model data without the need to write an ValueConverter like I did with the Race property.

Now we refactor our ViewCell and make it a custom class. From it’s code behind file you can now even access it’s elements using x:Name

<?xml version="1.0" encoding="UTF-8"?>
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="YourNameSpace.DogItemView">


  <StackLayout HorizontalOptions="Start" >
    <CheckBox State = "{Binding IsChecked}" />
    <Label x:Name="Name"  Text="{Binding Name}"  TextColor="Navy" FontSize="20"/>
    <Label x:Name="Race" Text="{Binding Race}"/>
    <Button Text="Add to Cart" Command="{Binding AddToCartCommand}"/>
  </StackLayout>
</ViewCell>

and our Page 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="Examples.DemoListViewPage">
  <ContentPage.Content>
    <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="Center">
      <ListView ItemsSource="{Binding DogList}" HasUnevenRows="True">
        <ListView.ItemTemplate>
          <DataTemplate>         
            <DogItemView BindingContext = "{Binding}" />
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

Looks cool, doesn’t it?

Virtual ObservableCollection

Virtualised collection views like ListView or CarouselView are great as they generate their views on the fly based on a DataTemplate. The problem is they need a collection that contains all elements that you want to display. Sometimes this is not feasible because the collection would be too big or it would take too long to load it completely from a remote location.

After some research I found out that the ItemViews as minimum need  an object that implements IReadOnlyList<T>, INotifyCollectionChanged as Itemsource and even there they only use the [int index] and Count property. So I came up with this handy class:

using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;

namespace Helpers{
    public abstract class VirtualObservableCollection<T> : IReadOnlyList<T>, INotifyCollectionChanged
    {
        public IEnumerator<T> GetEnumerator()
        {
            throw new System.NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public int Count {
            get { return ItemCountRequest(); }
        }

        public T this[int index]
        {
            get { Debug.WriteLine("Index: {0}",index);
                 return OnDataRequest(index);
            }
        }

        public event NotifyCollectionChangedEventHandler CollectionChanged;


        public void SignalCollectionChanged()
        {
            CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        protected abstract  T OnDataRequest(int index);
        protected abstract int ItemCountRequest();


    }
}

You only have to derive your own class from it and override OnDataRequest and ItemCountRequest. OnDataRequest has to return the item that should be displayed for a given index. ItemCountRequest must return the maximum number of items that will be displayed.

 

How to Distribute Files with your App

Often we need to distribute some files together with our App like a prepopulated database, settings files, image etc. To do this there are basically three methods:

Embedded Resoures

  • Quite good for Images like icons
  • read only
  • not directly accessable for file IO
  • Can be accessed from PCL Files
  • App has to be rebuilt

https://developer.xamarin.com/guides/xamarin-forms/working-with/files/#Loading_Files_Embedded_as_Resources

As Android Assets / iOS bundled Resource

  • read only, so you have to copy them somewhere else if you want to have  write access
  • not accessible from PCL without Dependency Service
  • App has to be rebuilt
  • Has to be added to each platform project differently

 

Android
  • read only
  • not directly accessable for file

Example of reading a JSON File:

using (var reader = new StreamReader(assets.Open("SampleData.json")))
{
   var json = new JsonSerializer();
   list = (List)json.Deserialize(reader, typeof(List));
}

 

iOS
  • read only
  • directly accessible for file
using (var reader = new StreamReader(File.Open("./Samples/SampleData.json", FileMode.Open,FileAccess.Read)))
{
   var json = new JsonSerializer();
   list = (List)json.Deserialize(reader, typeof(List));
}
return list;
 The path corresponds to the Folders below the Resoures folder of your iOS project.

Download from server at first startup

IMHO the most flexible solution.

  • App does not have to be rebuilt
  • writeable
  • directly accessable for file IO
  • can also be used to update an installed App

Often people shy way from this as it seems a lot of effort especially if you have a lot of files.

Luckily I happen to have published just yesterday a class calles FileStorage which offers a needful function called PopulateDataFolderFromZipUri

public async Task PopulateDataFolderFromZipUri(string uri, 
                                               string outFolder)
which will download a ZIP file from uri and extract it to outFolder which path is relative to your app’s data directory

 

What you always wanted to know about Gorilla Player….

One of the most requested features of Xamarin Forms is a visual Xaml Editor. Sure, it would be nice, but it would never show you how your App will look on different devices. So I think the way that the developers of Gorilla Player choose is the right one. It’s not too difficult to write a Xaml Page. After some time you do a good piece by copy and modify existing code or create your own custom views for reuse.  But it’s annoying to compile and deploy your App to see even minor design changes. Here comes Gorilla player into play.

Brand logo

So what is it? Gorilla Player let’s you preview your Xaml Files in real time on multiple devices or Emulators in parallel. Any change to your Xaml files are reflected immediately on all devices.

To make this work you have to install a Player App which is available in the App Stores and the Gorilla Server App on your PC. After starting the Server App you can connect as many devices as you want to the Server by starting the Player App. If you then open a Xaml File in VS or XS it will be automatically displayed on the devices.

Tip:
If the page is not displayed try opening another file in your IDE and then switch back to the Xaml file. If this don’t help go to the Tools->Gorilla menu and disconnect / connect your IDE.  Sometimes your Player App will not connect if you click on the discovered server. In this case switch to manual to connect.

This is how it looks like previewing  the same page on iOS on the VS iOS emulator in parallel to MS Android emulator.

monkey

This sounds pretty easy, but there are some pitfalls on your way:

  • If you use custom renderers and markup extensions and resources  will not be displayed.
  • Any bindings will not work 🙁

The solution for this is using the Gorilla SDK this actually allows you to include the Gorilla client into your App and therefore access all your assemblies including renderers, markup extensions, custom page base classes and resources. Sound great, BUT getting this set up is not as easy as it sounds:

  • Biggest problem, the documentation on the Gorilla Website is not up to date. There is a more complete one on their github page
  • Registering your assemblies can be tricky

I won’t repeat the content of their SDK documentation on github here. Instead I will add some things that I found important while working with gorilla:

  • Make sure that you add all assemblies that contain renderes etc. to the gorilla.json file AND register it in your App startup code using RegisterAssembyByType with types from all assemblies that you want to use.
  • Important include also the main PCL assembly of your App
  • Gorilla recommend adding the SDK to your App project. I personally prefer to have a separate GorillaDesign solution which loads and deploys fast to your device because you will have to deploy it every time you want to add a new assembly.  When I’m satisfied with the look I will copy the Xaml back to my App project.
  • You can provide Sample Data to your databindings using a json file that is also updated in real time. When I tried this I had problems to get this working together with the SDK. What I did is adding a static item source to my Xaml file. This way you can use all your Custom classes in bindings:

staticitemsource

Important: To make this work you have to include the name space containing your custom classes to the xaml file.

  • One general tip when tweaking Xaml design is to use the BackgroundColor that almost all visual Elements and Layouts have to see which dimensions these Elements really have like this here

gorilla

If you still have problems getting Gorilla to work, drop leave a comment or mention me on Slack and I will try to update this post with more information.

 

Hello world!

Hi,

after long thoughts I decided to start a blog too. My I have two goals with this blog.

  1. Share experiences that I made while developing, perhaps saving others time making not the same mistakes
  2. Write up information that I myself always forget while developing.

I hope you will enjoy reading.

Best

Thomas

P.S.: I’m not a native speaker so please have patience with my writing. I also will not spend a lot of time polishing the design  of my posts. I hope the content will make up for it.