More Functional ViewModels In Xamarin.Forms With C#

Xamarin.Forms is designed around MVVM, a two-way binding between a View and ViewModel. But with this comes an array of potential state issues. You have no control over the flow and timing of Visual State updates to your ViewModel.

Hence, I decided to see if I could develop an easy enough way to overcome some of these limitations.

Note: This is just a thought experiment. It’s not production ready, and probably has lots of limitations I haven’t even discovered yet. Go easy on me please 🙂

I also wanted to make this as simple as possible. Because if this is over-architected and complex, why would you bother using it. It has to be as easy or easier than your current workflow, and solve a problem, otherwise not many will use it. When developers are rushing to meet deadlines, the easiest route is normally what is taken.

Also because Xamarin.Forms is MVVM, I want to keep as much inline with this pattern as possible.

Stop Copying The VisualState

My first thought is why are we holding the state of the View in the ViewModel? The View is already holding it, so why do we want to clone it? All we really want, is a ViewModel full of Commands/Functions, that issue Visual State updates, or pushes new state updates to the View.

My main aim is to instead, setup something like this.

The VisualPush and Controller are still inside a ViewModel, that I bind to the BindingContext of a Page. Here is a quick look at how I created a ViewModel, VisualPush and Controller. Technically there is no reason for me to split the two, other than to make the concept a little easier to understand.

// This is still the BindingContext of the page.
// VisualPush and Controller instances are created upon construction
// in the BaseViewModel
public class MainViewModel : BaseViewModel<VisualPush, Controller> { }

// Think of this, as more of a container that you sends to the View.
public class VisualPush : BaseVisualPush
{
        // Look at me, you don't even need to set Fody or INPC here
        // And the set should be private. You don't want anyone updating it 
        // as they feel like it.
	public string LabelValue { get; private set; }
}

public class Controller : BaseController
{
	public Command UpdateCommand => new Command((text) =>
	{
                // Using Tuples to build a state change array
		var stateChange = ((nameof(VisualPush.LabelValue), text));

                // Send this StateChange array to the View
		VisualPush.Send(stateChange);
	});
}

MainViewModel

  • Is the BindingContext of the MainPage
  • Type VisualPush and Controller are created as readonly public properties

VisualPush

  • Contains all the possible properties your View will bind to
  • Notice, I haven’t even implemented INPC at this level

Controller

  • Has access to the VisualPush instance
  • Has Commands

Snapshot State On Action

Instead of sending a signal to your ViewModel, to start something, then get your Command to read all the state itself, send it all the details it needs from the Visual State, exactly when the action is performed.

This way you create a snapshot, and act upon that, rather than reading from potentially changing state. In this example, I just reference the Text property of the RandomEntry element, and send that through.

Notice, I just start my Bindings with VisualPush for any Values I want to receive, and Controller for any commands I want to send. Its push and pull, each class only goes in one direction (logically, that is).

<StackLayout>
    <Label Text="{Binding VisualPush.LabelValue}"
           VerticalOptions="Center"
           HorizontalOptions="Center" />
    <Entry x:Name="RandomEntry" />
    <Button Text="Update" Command="{Binding Controller.UpdateCommand}"
                          CommandParameter="{Binding Text, Source={x:Reference RandomEntry}}"/>
</StackLayout>

Side Note: If you need to send multiple values through a CommandParameter. To do this you will need to create an array. I did attempt this but couldn’t get anything working. It might require some updates to Xamarin.Forms XAML capabilities to manage it, or I need to think of another way to attempt it. Either way, my failed attempt is in the source code.

Send A Command

Looking at the UpdateCommand, we receive the Text value. It is a snapshot and now we don’t care if something has updated it since.

public Command UpdateCommand => new Command((text) => 
{ 
    // We could call a pure function with text as its input parameter. We don't need any Visual State information here.

    // Now we push a change to the View.
    var stateChange = ((nameof(VisualPush.LabelValue), text)); 
    VisualPush.Send(stateChange); 
});

We can now run a function with that value, and create what is called a Pure Function. A Pure Function is a function that’s output only changes dependant upon its input values. So we create a function without state, no DateTime or relying on other properties of the View, that could change without you knowing.

Next, we want to push a change to the view. We create a tuple, called stateChange as per the example. Very simply, it is nameOfProperty and newValue.

Then we call VisualPush.Send, and it sends it back to the View. This limits inputs to the Controller, and outputs via the VisualPush.

Summary

With this approach, we get a snapshot of the view, at the exact time the Command is executed, and can then run pure functions based on that, without having to wonder if the Visual State is going to change while the function is running.

This was purely a proof of concept, and I actually do think this could be a great way forward. I actually pushed this concept further, and you can view the new blog post in Functional ViewModels In Xamarin.Forms (Revision 2).

Would be happy to hear your comments on this approach. As I mentioned before, this is just a proof of concept, don’t attempt this in your production app just yet.


XAMARIN WEEKLY NEWSLETTER

Subscribe to a hand-picked round up of the best Xamarin development links every week. Published every Friday. Free.

Signup to Weekly Xamarin

* I do not maintain or run this newsletter, but I do recommend it.

Related Posts

Microsoft MVP | Xamarin MVP | Xamarin Forms Developer | Build Flutter

6 Comments

    1. Adam Pedley

      There is possibly a core concept similarity but its not that similar. I did look at Redux originally, but with it’s Actions, Listeners, Reducers etc, makes everything a little over complex in a Xamarin.Forms setting, by continually going against the framework.

  1. Rafal

    I think on android there is a similar pattern named MVI (Model-View-Intent) maybe that approach you can use as inspiration…. Anyway good post.

    1. Adam Pedley

      Thanks 🙂 I think there are some similar concepts. The basics of wanting to a have single state, then pure functions, I think is the core at many things such as Rx, Redux, MVI. But none of them exactly fit into a framework designed from the ground up, purely for MVVM.

      That is the problem I am trying to deal with here. How do we work with an MVVM pattern, that allows a more functional programming style, and creates state snapshots to work on.

      Something that developers could easily transition to, would not be any extra work, and would help create more stable apps.