Removing Row and Column Spacing from Xamarin.Forms Grid

Xamarin.Forms Grid allows us to specify spacing between individual rows and columns using RowSpacing and ColumnSpacing properties. While this is no doubt a useful feature, the unfortunate fact is that these are not set to 0 by default.

The problem

If you check the source code on GitHub, you can find the following dependency property declarations:

public static readonly BindableProperty RowSpacingProperty =
BindableProperty.Create("RowSpacing", typeof(double), typeof(Grid), 6d, …);
public static readonly BindableProperty ColumnSpacingProperty =
BindableProperty.Create("ColumnSpacing", typeof(double), typeof(Grid), 6d, …);

The default value is 6 for both properties, which means all Grids you create will feature this inner spacing by default. Consider the following Grid:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<BoxView BackgroundColor="#f65d35" />
<BoxView BackgroundColor="#81bb05" Grid.Row="0" Grid.Column="1" />
<BoxView BackgroundColor="#04a5f0" Grid.Row="1" Grid.Column="0" />
<BoxView BackgroundColor="#ffba07" Grid.Row="1" Grid.Column="1" />
</Grid>

view raw
DefaultSpacing.xaml
hosted with ❤ by GitHub

This XAML yields a rather nice logo, but it usually is not what we want, especially if we want a pixel-perfect layout:

Default Grids spacing in action
Default Grids spacing in action

Setting RowSpacing and ColumnSpacing to 0 solves the problem immediately, but it is easy to forget to do it. How could we do it more generally?

Project-wide solution

Who are we gonna call to resolve our problem? Styles! Defining a default Style targeting a specific element type is easy. To make it work project-wide, we can put it in <Application.Resources> in App.xaml of our shared project or .NET Standard library:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GridSpacing.App">
<Application.Resources>
<Style TargetType="Grid">
<Setter Property="ColumnSpacing" Value="0" />
<Setter Property="RowSpacing" Value="0" />
</Style>
</Application.Resources>
</Application>

Et voilà! All Grids in our project are now spacing-less!

No spacing, no copyright infringement intended
No spacing, no copyright infringement intended

Using ResourceDictionary

To improve the reusability of our solution, we can move our style to a separate resource dictionary file To do that we create a new empty XAML file. There is no built-in template for this type of XAML file, so you can start with a ContentView template for example and rewrite appropriately. I named my dictionary Reset.xaml and its XAML looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GridSpacing.Reset">
<Style TargetType="Grid">
<Setter Property="ColumnSpacing" Value="0" />
<Setter Property="RowSpacing" Value="0" />
</Style>
</ResourceDictionary>

view raw
Reset.xaml
hosted with ❤ by GitHub

The code-behind is straightforward as well:

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace GridSpacing
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Reset : ResourceDictionary
{
public Reset ()
{
InitializeComponent();
}
}
}

view raw
Reset.xaml.cs
hosted with ❤ by GitHub

Now we include the file in the <Application.Resources> resource dictionary:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GridSpacing.App"
xmlns:local="clr-namespace:GridSpacing">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:Reset />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>

view raw
App.xaml
hosted with ❤ by GitHub

When we rerun the app, it will look the same as before, but ResourceDictionary now allows us to better organize our resources. There is no problem in putting resource dictionaries in a separate assembly which can be reused across multiple apps. To learn even more tricks, check out the official blog post from Xamarin and documentation.

Summary

The non-zero default of RowSpacing and ColumnSpacing properties can be a bit confusing, especially for developers coming from WPF and UWP development. Our default style helped us avoid the distinction. Refactoring to ResourceDictionary opens the door for better resource organization and potential of storing a set of multiple “reset” styles in one location.

Buy me a coffeeBuy me a coffee

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.