Xamarin is a wonderful company that produces tools to build multiplatform app written in C# and .NET. Recently Xamarin introduced Xamarin.Forms, allowing for even more code reuse in the UI (User Interface) without sacrificing the ability to produce native code (and UI and UX) on each specific platform. Xamarin.Forms is based on the XAML and data binding concepts that we (as Windows and Windows Phone developers) already know and love to use.
If you don’t know what I’m talking about, please look at the great Xamarin intro by James Montemagno on Channel 9.
While using Xamarin Forms for my actual project, I’ve found some differences of Xamarin XAML language implementations from Microsoft one that I think is worth noting. I hope this post can be helpful to avoid some pitfalls and to be proficient on developing with it.
Beside small nouns differences that I can live with, like:
|Xamarin XAML||Microsoft XAML|
|<StackLayout />||<StackPanel />|
|<Label />||<TextBlock />|
I’ve also found other more subtle differences that can drive mad the unknowing developer (like me, while learning the hard way how to live with it):
1. The lack of Margin property
2. The default value of Spacing property
3. The default “Auto” length of single column and/or row Grid
Let’s see them one by one.
The lack of Margin property
Xamarin Forms use the CSS Box definition:
The problem is that Microsoft XAML implement the Margin and not the Padding, while Xamarin XAML implement the Padding and not the Margin.
I think this is the most disruptive change that prevent using almost the same XAML on Microsoft and Xamarin, because it’s not a “change name” game, is about a functionality that needs to be migrated from children to container.
Moreover, because the padding property is defined in the “Layout” object level and in the “Page” object but not in the View object, many objects (i.e. Label, Button, etc.) do not inherit it.
Look at the (partial) Xamarin Forms object tree to see what I’m saying:
Apart from the architectural point of view (maybe better choice would have been to define it as a property of the “VisualElement” object), there is a more practical consequence of this implementation detail. Each time you need to define a margin to separate two adjacent elements, you need to wrap each of them inside a ContentView (the simplest layout descendant) to set the padding property.
Consider this simple Microsoft XAML example:
The equivalent Xamarin XAML is:
On some specific scenario (like the above one) Xamarin XAML came to rescue supporting the spacing concept of CSS Box Model: on “StackLayout”, we have the “Spacing” property while on “Grid” we have the “RowSpacing” and “ColumnSpacing” properties.
Knowing that, we can refactor the previous example like this:
Apart from this special case, in general the lack of Margin property is something that I hope Xamarin will solve implementing it in a future release of Xamarin Forms.
The default value of Spacing property
This is simple to describe and use, once you know it: when using StackLayout or Grid bear in mind that their respective spacing properties (Spacing for StackLayout and both RowSpacing and ColumnSpacing for Grid) have a default value of six. If you don’t want spacing, you need to define those properties explicitly setting the respective values to zero.
This is a bit annoying and I would prefer to have a predefined value of zero. If you agree, please vote for it. J
The default “Auto” length of single column and/or row Grid
When using a Grid, each time we do not define a set of rows and/or columns, the system presume we need a single row and/or column and implicitly define just one row and/or one column. While on Microsoft XAML the length property (“Height” for the row, “Width” for the column) default to “*” (i.e. take all the available space given by the container and offer it to his children), I learned (the hard way) that the default length of an implicit definition of “Row” and/or “Column” in Xamarin Forms is “Auto”.
With Microsoft XAML, this code:
Give this obvious result:
Note that the two row’s backgrounds (purple and blue) cover the red background of the Grid container.
If we try to use the same XAML on Xamarin Forms, we need to do minor name adjustments and explicitly define zero spacing:
However, as you can see in the below image, we do not obtain the hoped result:
Note that this time the two row’s backgrounds (purple and blue) do not extend horizontally to the full available space. This is a strange behavior, because the containing grid do extend to the full available horizontal length (we know it because the red background of the grid fill all the space), but the two inner grids do not.
The reason, as explained before, is due to the Xamarin Forms default length value of the implicitly defined single column, set to “Auto”. In this case, the containing grid do take the entire available place but set the horizontal width of the column to the width of his largest children.
The easy (when you know it J) solution is to explicitly define also the single column and set his length to “*”:
To have the desired output:
The good news are that this will change on Xamarin Forms 1.2.3 release. Until then beware of the details!
That’s all folks, happy coding!