Supported Linq query expressions in Realm

Sooner or later, you’ll come to the point, that you don’t only want to get objects by Id or the whole set of objects of a specific type in Realm. The easiest, but probably most unsophisticated way to do it, would be just use a function on a Linq-Where statement. That’s easy and has reasonable performance, no need to iterate and implement it yourself. But it actually is a big waste of resources, because depending upon the function, every single element needs to be evaluated.

But there is a better way to do so, eventhough it’s support in Realm is very confined. You can use Linq-Expressions. In the next table you find a plan, on what is supported or not:

ExpressionExampleRealmInfo
Int-Query
Double-Query
String-Query
class.Number==4
class.Number>3.4
class.Number<=2
class.Text==”Hello World”
String-Functions:
Contains, StartsWith, EndsWith
class.Text.StartsWith(“T”)as StringComparison you can use Ordinal or OrdinalIgnoreCase
advanced calculationclass.Number*20>100no left-side operations are supported, but right-side operations
Same-Object Comparisonclass.Number>class.Number2only comparison with constant values are supported
List-Functionsclass.List.Contains(3)
Sub-Object-Accessclass.SubClass.Number==1
Take()Take(20)
Skip()Skip(5)

That’s really not a lot. Actually it ends up with numeric type comparisons (==,<,>..) and some string-Comparer (==,Contains, StartsWith, EndsWith). I really hope Mongo Inc. will spend some more time on implementing more Linq-Expression features in Realm.

But actually there is a (little) work around (which I didn’t yet check out in terms of performance). You can use the Filter-function, which takes a query that is inspired by NSPredicate. (you can find more details here)

ExpressionFilter
advanced calculation
Same-Object ComparisonSubClass.Number>Number
List-FunctionsANY SubClassArray.Number>10
ANY or SOME works only with RealmObject-Arrays, not with atomic type arrays
Sub-Object-AccessSubClass.Number>20
Take()
Skip()

Summarizing my investigation and research on this, I can say: There’s space for improvement. I am very keen on finding out, whether MongoRealm will have a more sufficient way to query data.

User Access Management in Realm

As I already stated before, I love Realm.io. It’s a pretty cool object oriented database, with a very mighty synchronization mechanism, that helps you build mobile apps just right out of the box. But that’s not the end of the line.. It also ships with a very mighty user management feature.

When you develop mobile apps, you sooner or later want users to get authenticated. You need a user management, with registration, authentication, and permission management. That’s all but easy.

Realm delivers all of it, with some easy steps.

  1. User registration
    var usr = await User.LoginAsync(Credentials.UsernamePassword("Tom", "test", true), new Uri("realmUrl"));
    // an exception will be thrown, when the user already exists
  2. User login
    var usr = await User.LoginAsync(Credentials.UsernamePassword("Tom", "test", false), new Uri("realmUrl"));

Now that you have a user registered and logged in, you can create as many realms as you like. But you can only create realms with your UserId, in most cases this is not the Username. But don’t panic, you don’t need to store it somewhere. When you open a Realm, just add a Tilde, which will automatically get replaced with your UserId.

FullSyncConfiguration conf = new FullSyncConfiguration(new Uri("~/MyLittleRealm", UriKind.Relative));
var realm = Realm.GetInstance(conf);

Pretty easy, isn’t it? But that’s not all. Let’s assume we have an App to manage your shopping list. That’s probably enough, but you also want to share your shopping list with your wife or kids. Everyone using your App will actually have it’s own list, but can’t access the others. But you know what realms they are using, so you could synchronize them too, perhaps it is something like <UserId>/ShoppingList . But first of all you don’t have their UserId (this is not the username!) and also no permission to access it. A user needs to actively grant someone else access to their Realms:

await User.Current.ApplyPermissionsAsync(PermissionCondition.UserId("someonesUserId"), "~/ShoppingList", AccessLevel.Read | AccessLevel.Write);

You can even choose if the user can read or read and write your Realm. But how do we get the UserId?

There are two approaches to that challenge:

  1. you can store the UserId in a public realm, this is okay, but not a very secure solution
  2. your App can offer a way to directly send the UserId to others using WhatsApp, NFC or a QR-Code .. that is easy and everyone has complete control to their data (even though it’s only an ID)
  3. Didn’t I just talk about two? Ok, I think there are probably more than that, there could be something like “Sync”-Mode.. a User can write an offer in a public realm, stating he wants to share his shopping list with a user with username “xy”, the App of user “xy” could react upon that offer and publish its UserId.

By the way: When you are using an external Authentication (like an Identity-Server or similar) that offers a JWT-Token, the UserId will be the same as the Username.

Using Realm Notifications in .Net

There is a documentation on Realm.io, that describes how to hook up on a ROS (Realm Object Server) to observe changes on specific Realms, RealmObjects or whole instances. So there is no need to actually download the whole Realm, since it “sees” the changes directly on the server. It is also pretty cool, that you don’t have to load the assemblies that contain the correct RealmObjects (and version), because it uses the .Net DynamicObject feature.

https://docs.realm.io/sync/backend-integration/data-change-events#integrating-with-a-3rd-party-api

Sadly, this only works with node.js not in .Net…

There is currently only one work around, that really works with .Net Standard, that I have found. You open the specific Realm in dynamic mode and use the method SubscribeForNotifications. Be sure to have a separate Thread running for the notifications to work properly.

static async Task Main(string[] args)
{
var adminUser = await User.LoginAsync(Credentials.UsernamePassword("aUser", "****", false), new Uri("https://rosurl"));
var realmSyncConfig = new Realms.Sync.FullSyncConfiguration(
new Uri("SomeRealm", UriKind.Relative), adminUser);
realmSyncConfig.IsDynamic = true;
Nito.AsyncEx.AsyncContext.Run(async () =>
{
var realm = await Realm.GetInstanceAsync(realmSyncConfig);
var realmCollection = realm.All("Organization") as RealmCollectionBase<RealmObject>;
var token = realmCollection.SubscribeForNotifications(RealmChanged);

while (true)
{
// you can use a cancellation token here
await Task.Delay(1000);
}
token.Dispose();
realm.Dispose();
});
Console.ReadLine();
}

private static void RealmChanged(IRealmCollection<RealmObject> sender, ChangeSet changes, Exception error)
{
/* here you can handle changes */
}

There are some disadvantages when you use this solution:
1. The Realm that you want to subscribe changes on will be fully synced. (So it’s not a good solution for very large Realms)
2. You can’t just watch your whole instance, you need to actually know the full name of your Realm

Performance of loading Xaml dynamically in Xamarin.Forms

As I mentioned in a previous post, you can quite easily load Xaml dynamically in your Xamarin.Forms App. But how about performance? How long does it take in comparison to “regular” loading of pre-compiled Xaml.

It’s anything but easy to really measure this. We could eventually use LoadFromXaml and measure the differences. I decided to create DataTemplates and use the CreateContent() method to create the actual Control.

<DataTemplate x:Key="Test1">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="*" />

    </Grid.RowDefinitions>
    <Label Text="Hello World!" />
    <Button Grid.Row="1" Text="Press me" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="Test2">
    <dynamiccontrol:XamlView>
        <dynamiccontrol:XamlView.Xaml>
            <![CDATA[
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="*" />

                </Grid.RowDefinitions>
                <Label Text="Hello World!" />
                <Button Grid.Row="1" Text="Press me" />
            </Grid>
            ]]>
        </dynamiccontrol:XamlView.Xaml>
    </dynamiccontrol:XamlView>
           
</DataTemplate>

You can see that the Xaml is quite easy, but loading it dynamically takes over 20 times longer than compiled Xaml.

I tried to create 10,000 controls and measured the following values:
Compiled Xaml: 5.8s
Dynamic Xaml: 133.1s

I know the test is not very representative, but you should always keep in mind that there may be a performance problem when using this method. Especially when you want to create dynamic Layouts in ListViews.

You can slightly boost performance (5-10%), when you load the whole DataTemplate from Xaml, and then create the Control with it.

Dynamic DataTemplate: 124s

Never ever use Task.Result in Xamarin.Forms! Why?

I recently stumbled over a deadlock in our code. Someone called a method, that returned a Task, and instead of awaiting it, he called:

var res = Method().Result;

I reason for this code was just plain laziness, because using await requires an async-context, which probably isn’t that easy to achieve. But what’s the reason for that deadlock, and why is awaiting the result actually resolving it?

I don’t want to dick very deeply into the Task Parallel Library (TPL). But let’s just make clear, what a task is. A task is a “unit of execution”, it has no direct link to Threads (even though it’s in the same namespace). A Thread can run tasks, there can be one or more Threads in your program. Let’s assume that Threads run in parallel.

So now let’s make up some setting, we call a method (which returns and starts a Task, that’s what “async Task” does) and then wait for the result by calling “.Result”. That call will actually block the current thread and wait for the second task to finish.

Result is working

When we look at the graphic above, we see that this call is working. We actually block Thread 1, but we have not created a deadlock. But we can never be sure, that the TaskScheduler (it is planning what Tasks runs on which Thread) really runs Task2 on Thread2. As soon as the TaskScheduler decides to run Task2 on Thread1, we have a classic deadlock:

DeadlockTask

But what is the difference to async/await pattern?

A couple of years ago, a friend described async-await pattern as syntactical sugar, it’s not a language feature, nor a real pattern. There is something true to that, but it makes programming Tasks so much easier. It actually splits your code into separate parts, and calls them in a sequence. So there will be no busy wait, no matter which Thread the Task we are waiting for is executed on.

TaskAsyncAwait

Remove whitespaces of a string in C#

This seems to be really simple, so why am I writing this blog post?
Everyone I asked, had a different idea to achieve this, the first idea was to use Regular Expressions, which is really straight forward and simple, but there are several other methods with quite different performance.

Let’s have a look at all methods that came in mind:
1. String Replace
2. Regex
3. split directly with whitespace character
4. split & join each character
5. use a StringBuilder
(this list may not be complete, but I focused on these methods)

// string replace
Stopwatch sw = Stopwatch.StartNew();
int n = 10000;
for (int i = 0; i < n; i++)
{
    var strRes = testString.Replace(" ", "");
    strRes = strRes.Replace("\t", "");
    strRes = strRes.Replace("\n", "");
    strRes = strRes.Replace("\r", "");
    //if (expected != strRes)
    //    throw new Exception();
}
sw.Stop();
Debug.WriteLine(sw.Elapsed);
// regex replace
sw.Restart();
for (int i = 0; i < n; i++)
{
    var strRes = Regex.Replace(testString, "\\s+", "");
    //if (expected != strRes)
    //    throw new Exception();
}
sw.Stop();
Debug.WriteLine(sw.Elapsed);
// split
sw.Restart();
for (int i = 0; i < n; i++)
{
    var parts = testString.Split(new[] { '\t', '\r', '\n', ' ' }, StringSplitOptions.RemoveEmptyEntries);
    //var parts = testString.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);
    var strRes = string.Join("", parts);
    //if (expected != strRes)
    //    throw new Exception();
}
sw.Stop();
Debug.WriteLine(sw.Elapsed);
// split 2
sw.Restart();
for (int i = 0; i < n; i++)
{
    var parts = testString.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);
    var strRes = string.Join("", parts);
    //if (expected != strRes)
    //    throw new Exception();
}
sw.Stop();
Debug.WriteLine(sw.Elapsed);
// StringBuilder
sw.Restart();
for (int i = 0; i < n; i++)
{
    StringBuilder resSb = new StringBuilder();
    foreach (var chr in testString)
    {
        if (chr != '\t' && chr != '\r' && chr != '\n' && chr != ' ')
        {
            resSb.Append(chr);
        }
    }
    var strRes = resSb.ToString();
    //if (expected != strRes)
    //    throw new Exception();
}
sw.Stop();
Debug.WriteLine(sw.Elapsed);

The Results

1. String Replace: 41ms
2. Regex: 113ms
3. split directly with whitespace character: 27ms
4. split & join each character: 27ms
5. use a StringBuilder: 9ms

Dynamically create controls in Xamarin Forms

This is a very broad topic. You can actually always dynamically create controls in code behind, by just adding them to the UI during runtime. This is very easy, but it’s not generic at all, you need to code everything you would actually do in Xaml.

Another solution (which I actually prefer) is to use a ListLayout (maybe a Bindable StackLayout) and use a TemplateSelector to switch between pre defined DataTemplates based on the ViewModel, that is being used. But this will actually not give you more flexibility, but it’s definitely a better solution than the first shot.

We actually want something really flexible, we try to achieve instanciating an unknown Xaml from whatever source we have (Text, Internet, UserInput,.. ), and even provide binding to further use the UserInput in ViewModel. So there are 2 parts to this:
1. load xaml during runtime,
2. somehow achieve binding.

When you have a look in your obj-folder of a compiled Xamarin app, you will find a file called something like “MainPage.xaml.g.cs”

[global::Xamarin.Forms.Xaml.XamlFilePathAttribute("MainPage.xaml")]
    public partial class MainPage : global::Xamarin.Forms.ContentPage {
        
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "2.0.0.0")]
        private void InitializeComponent() {
            global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(MainPage));
        }
    }

There is another overload of the global extension function Xamarin.Forms.Xaml.Extensions.LoadFromXaml(..) which takes a string representation of your xaml to create a control.

We can use this, to create a ContentControl with a BindableProperty, which creates the given Xaml at runtime.

public class XamlView : ContentView
{
       
    public static readonly BindableProperty XamlProperty =
                            BindableProperty.Create(nameof(Xaml), typeof(string), typeof(XamlView), propertyChanged: OnXamlChanged);

    private static void OnXamlChanged(BindableObject bindable, object oldValue, object newValue)
    {
        try
        {
            var xamlView = (XamlView)bindable;
            ContentView view = new ContentView();
            // we add the default xaml namespace to our surrounding ContentView,
            // so it doesn't need to be defined in xaml
            view = view.LoadFromXaml("" +
                (xamlView.Xaml ?? string.Empty) +
                "");
            xamlView.Content = view;
        }
        catch (Exception ex)
        {
            // we should actually handle that exception, maybe put it on the screen as label
        }
    }

    public string Xaml
    {
        get => (string)GetValue(XamlProperty);
        set => SetValue(XamlProperty, value);
    }
}

usage:

<Grid BackgroundColor="Red">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Entry x:Name="XamlEditor" Text="{Binding ContentXaml}" />
    <dynamiccontrol:XamlView
        Grid.Row="1"
        Xaml="{Binding ContentXaml}" />
</Grid>

You could also bind the XamlView.Xaml directly to an Entry.Text using ReferenceBinding, but I prefer using a ViewModel instead.

And this is how it looks like:
XamlView

In my next post, I will talk about binding the Data from the XamlView to a ViewModel.

Copy an entire synced Realm

In our company, we use realm.io as mobile Database with the ROS Cloud to sync data between mobile devices and the server. Main advantage is, that we can build Apps in a fraction of time, without juggling with synchronization.

One of our main challenges was the disability to copy data from one realm to another. But there is still a good solution for this, even though you have to do a lot of coding for that.

Motivation

There are a lot of reasons, why copying realms is a really neat feature. First of all would be versioning your data. But it’s also very neat, when you have several instances (for development, testing etc.) to copy the whole data when you go productive or need some test data in development.

Challenge 1: generating the Schema

When we copy one realm to another, we actually don’t know the used types. We could include a library which contains the types, but then our “RealmCopy” will only work for a specific realm, which is really baloney. That’s as if you develop a copy-program, that can only copy text-files.

So we need to read the source realm, get the schema and create the same schema in the destination. In .Net we can open a realm dynamically, which is pretty cool, because this gives us a chance to get the information we need. Only problem – we can not create or change a schema on a dynamically opened realm.

Solution? We can create dynamic types, and open the destination realm, this will automatically create a schema on the destination realm. (It’s really a little bit awkward, but that’s currently the only chance in .Net – with Javascript, we can mutate the realm directly, but that’s probably due to the nature of that language)

RealmCopy

Open a realm as dynamic:

var username = "";
var password = "";
var realmUrl = "";
var realmName = "TestRealm";
var user = await User.LoginAsync(Credentials.UsernamePassword(username, password, false), new Uri(realmUrl));

var configuration = new FullSyncConfiguration(new Uri(realmName, UriKind.Relative), user)
{
IsDynamic = true
};
var srcRealm = await Realm.GetInstanceAsync(configuration);

now we can go through the scheme and create types:

var types = new List();
foreach (var scheme in schemasToProcess)
{
// create an assembly for our type
var assemblyName = new AssemblyName($"SomeAssemblyName{name}");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
// create an module for the type
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
// get the typebuilder as
var typeBuilder = moduleBuilder.DefineType(name,
TypeAttributes.Public |
TypeAttributes.Class
, parent);
// add properties to type
foreach (var prop in schema)
{
var attributes = new List();
Type propType;
// woven property is needed, so Realm will add it to the destination schema
attributes.Add(typeof(WovenPropertyAttribute));
if (prop.IsPrimaryKey)
{
// add primary key attribute
attributes.Add(typeof(PrimaryKeyAttribute));
}
else if (prop.IsIndexed)
{
// add indexed attribute
attributes.Add(typeof(IndexedAttribute));
}

// get the property type
propType = prop.GetPropertyType(knownTypes);

// set required attribute, when its not nullable
if ((prop.Type & PropertyType.Nullable) != PropertyType.Nullable)
{
attributes.Add(typeof(RequiredAttribute));
}

// create the property
MyTypeBuilder.CreateProperty(typeBuilder, prop.Name, propType, attributes.ToArray());
}
types.Add(typeBuilder.CreateType());
}

In one of my previous blog posts I mentioned how to create types using the TypeBuilder, so I won’t code it out here.
The function GetPropertyType is an extension, it’s just a mapping of the Realm-PropertyType to a CLR type.
Now we can open the destination Realm:

var configuration = new FullSyncConfiguration(new Uri(realmName, UriKind.Relative), user);
configuration.ObjectClasses = types;
var destRealm = await Realm.GetInstanceAsync(configuration);

Challenge 2: copying the realm

This doesn’t actually seem to be a challenge. We go through all objects in source realm and copy it to a new RealmObject, which is created in destination. You can actually use our generated types to open the source realm and use straight reflection for mapping all properties. But be careful, if you did something wrong, you would probably mutate the source realm (what you might not want). You can stick to the dynamic Realm instead and use CallSiteCache to read the properties and reflection to set it to the destination object. (more infos)

Challenge 3: cascaded objects

An object may not only reference atomic types, but also have other RealmObjects as properties. It can even contain cycles. This is really tricky, I solved it by initially creating a TypeBuilder for each SchemaItem, then we can use this TypeBuilder as a PropertyType, without building the actual type. Creating objects can be done recursively, but keep track of the objects, you already created, so you can avoid cycles.

If you have any questions, feel free to ask. ..have fun coding.

Move Controls in Xamarin.Forms App with your finger

…or Mouse.. or Pen.. or nose, whatever you like. In WPF this is very easy accomplished, because Drag&Drop is a main UI feature in Windows. Each OS implements this feature slightly different, that’s why there is no such generic solution for all platforms. Microsoft proposes a solution called TouchEffect, which implements a specific Effect for each platform. (https://docs.microsoft.com/de-de/xamarin/xamarin-forms/app-fundamentals/effects/touch-tracking)

But there is still another and quite simple solution, you can use gestures (esp. the PanGesture) for that, with slight limitations.

MoveViewXamarin

The PanGesture

The PanGesture is actually a touch based Drag&Drop. You put the finger down on the screen and moved it around until you raise your finger. The PanGesture will always fire it’s event while the finger is moving around and will be quitted with the coordinates (0,0)

The Implementation

The implementation is quite simple, actually there are only a few lines of code:
1. when panning starts: save current Translation of View
2. while panning: set translation to the starting value + panning value
3. when panning finished: reset variable for starting value

Developers are lazy people, we don’t want to copy that implementation on every View. So the trick is, to use an attached property, so we can use it on every View and even bind it to a ViewModel.

The Code

public static class MoveView
{
    #region attached properties: CanMove
    public static readonly BindableProperty CanMoveProperty =
            BindableProperty.CreateAttached("CanMove", typeof(bool), typeof(View), false,
                propertyChanged: OnCanMoveChanged);

    private static void OnCanMoveChanged(BindableObject bindable, object oldValue, object newValue)
    {
        if ((bool)newValue && bindable is View view)
        {
            PanGestureRecognizer pangest = new PanGestureRecognizer();
            pangest.PanUpdated += Pangest_PanUpdated;
            view.GestureRecognizers.Add(pangest);
        }
    }
    public static bool GetCanMove(BindableObject bindable)
    {
        return (bool)bindable.GetValue(CanMoveProperty);
    }

    public static void SetCanMove(BindableObject bindable, bool value)
    {

        bindable.SetValue(CanMoveProperty, value);
    }
    #endregion

    // saves the translation state on start, it's okay to have it static
    // because we can only move one item at a time
    static Point? _translationStart = null;
    private static void Pangest_PanUpdated(object sender, PanUpdatedEventArgs e)
    {
        if (sender is View view)
        {
            if (e.TotalX == 0 && e.TotalY == 0)
            {
                // movement has end, reset
                _translationStart = null;
            }
            else
            {
                if (_translationStart == null)
                {
                    (view.Parent as Layout)?.RaiseChild(view);
                    _translationStart = new Point(view.TranslationX, view.TranslationY);
                }
                view.TranslationX = e.TotalX + _translationStart.Value.X;
                view.TranslationY = e.TotalY + _translationStart.Value.Y;
            }

        }
    }
}

Usage

 <Frame BorderColor="Red" BackgroundColor="Bisque"
                   dashboard:MoveView.CanMove="True"
                   HeightRequest="100" VerticalOptions="Center"
                 />

Limitations

– only when the parent is a layout, it will raise the View that is moved to the topmost position (only in respect to the parent, not overall)
– you can simply move the View outside of its parent, but then you will not be able to move it back in

Please feel free to use the code and change it as you like. If you find bugs, you may fix them. I would also be happy if you leave me some notes.

Xamarin.Forms FlowLayout

Motivation

I recently faced the challenge to add Items of different sizes to a Page on a Xamarin.Forms App. The result should be some kind of a Dashboard with Diagrams and info boxes on it. Some diagrams are smaller, some bigger.

The first thing, that came in mind, was a FlexLayout, but this looks a little bit odd to me, because the controls on the main axis share the same size in the secondary axis. That is okay if all controls have the same height or width, but this is not the case.

FlexLayout Xamarin.Forms App

But what I actually want is something like this:

FlowLayout - Xamarin.Forms App

It’s very tough to arrange the children of a Layout, when every control has a free size defined. To solve this problem, we need to divide the available area in uniform sections. Using this approach, each control can define it’s size in units, and will be placed on the next available free spot.

Simulator Screen Shot - iPhone 11 - 2020-02-20 at 22.30.18

The Algorithm

  1. The FlowLayout needs a UnitSizeRequested in pixels, we need to calculate how many items can fit vertically and horizontally based on a size of a unit. Afterwards we need to find the actual UnitWidth and UnitHeight so that the whole area of the control is used.
  2. There need to be two attached properties for the child elements, so each element can specify its HorizontalUnits and VerticalUnits.
  3. Finally we create an array as a representation of the FlowLayout so we can arrange the Controls on it.

The Code

using System;

using Xamarin.Forms;

namespace Dashboard
{
    public class FlowLayout : AbsoluteLayout
    {
        #region attached properties: HorizontalUnitsProperty
        public static readonly BindableProperty HorizontalUnitsProperty =
                BindableProperty.CreateAttached("HorizontalUnits", typeof(int), typeof(FlowLayout), 1);
        public static int GetHorizontalUnits(BindableObject view)
        {
            return (int)view.GetValue(HorizontalUnitsProperty);
        }

        public static void SetHorizontalUnits(BindableObject view, int value)
        {
            view.SetValue(HorizontalUnitsProperty, value);
        }
        #endregion
        #region attached properties: VerticalUnitsProperty
        public static readonly BindableProperty VerticalUnitsProperty =
                BindableProperty.CreateAttached("VerticalUnits", typeof(int), typeof(FlowLayout), 1);

        public static int GetVerticalUnits(BindableObject view)
        {
            return (int)view.GetValue(VerticalUnitsProperty);
        }

        public static void SetVerticalUnits(BindableObject view, int value)
        {
            view.SetValue(VerticalUnitsProperty, value);
        }
        #endregion

        #region properties
        public double UnitSizeRequested { get; set; } = 100;
        public double UnitWidth { get; private set; }
        public double UnitHeight { get; private set; }
        #endregion
       

        protected override void OnSizeAllocated(double width, double height)
        {
            // when the control allocates the size, we will arrange the children
            base.OnSizeAllocated(width, height);
            if (width>0 && height>0)
            {
                ArrangeChildren();
            }
        }

        

        public void ArrangeChildren()
        {
            // do the calculation (step 1)
            int horizontalUnitCount = (int)(Width / UnitSizeRequested);
            int verticalUnitCount = (int)(Height / UnitSizeRequested);
            bool[,] dashArray = new bool[horizontalUnitCount, verticalUnitCount];
            UnitWidth = UnitSizeRequested + (Width % UnitSizeRequested) / horizontalUnitCount;
            UnitHeight = UnitSizeRequested + (Height % UnitSizeRequested) / verticalUnitCount;
            foreach (var child in Children)
            {
                // for each child - find the 
                var rect = FindFreeRectangle(dashArray, GetHorizontalUnits(child), GetVerticalUnits(child));
                if (rect != null)
                {
                    AbsoluteLayout.SetLayoutBounds(child, rect.Value);
                }
                else
                {
                    // this control can not be placed ... so just skip it
                    AbsoluteLayout.SetLayoutBounds(child, new Rectangle(0, 0, 0, 0));
                }

            }
        }

        private Rectangle? FindFreeRectangle(bool[,] dashArray, int xCount, int yCount)
        {
            Rectangle res;
            for (int y = 0; y  dashArray.GetLength(1)
                )
                return false;

            for (int xx = x; xx < x + xCount; xx++)
            {
                for (int yy = y; yy < y + yCount; yy++)
                {
                    if (dashArray[xx, yy] == true)
                        return false;
                }
            }
            // now reserve fields
            for (var xx = x; xx < x + xCount; xx++)
            {
                for (var yy = y; yy < y + yCount; yy++)
                {
                    dashArray[xx, yy] = true;
                }
            }
            return true;
        }

      
    }
}

Caution: This code is not complete, perhaps you can not use it with the BindableLayout-Extension. Feel free to copy the code and change it as needed. Be careful in choosing the right UnitSizeRequested, a small unit will probably result in a rather bad performance.

Usage

<FlowLayout BackgroundColor="Black" >
        <Frame BorderColor="Yellow" BackgroundColor="Gray" CornerRadius="0" 
                FlowLayout.HorizontalUnits="1"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Gray" BackgroundColor="HotPink" CornerRadius="0" 
                FlowLayout.HorizontalUnits="1"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Blue" BackgroundColor="Honeydew" CornerRadius="0" 
                FlowLayout.HorizontalUnits="1"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Red" BackgroundColor="Bisque" CornerRadius="0" 
                FlowLayout.HorizontalUnits="4"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Green" BackgroundColor="CadetBlue" CornerRadius="0" 
                FlowLayout.HorizontalUnits="3"
                FlowLayout.VerticalUnits="3"
                 />
</FlowLayout>