Model-View-Update (MVUX)

Model-View-Update has become an increasingly popular choice for developers looking to have a more functional approach to building user interfaces. In this module, we will be looking at how to use the MVUX pattern to build our UI. MVUX is a pattern that is similar to the MVU pattern but has been specifically designed to work with data binding.

To learn more about MVUX, refer to the MVUX Overview.

Getting Started

Create a new record called MainModel using the following code that creates two IState properties that represent whether the application is using the dark theme (IsDark) and the current Calculator instance:

namespace SimpleCalculator;

public partial record MainModel
{
    public MainModel()
    {
        Calculator = State.Value(this, () => new Calculator());
        IsDark = State<bool>.Value(this, () => false);
    }

    public IState<bool> IsDark { get; }

    public IState<Calculator> Calculator { get; }

    public async ValueTask InputCommand(string key, CancellationToken ct) =>
        await Calculator.Update(c => c?.Input(key), ct);
}

Binding to properties in the UI

With our model created we will now need to set up our DataContext and create some bindings.

To start let's set the DataContext in the MainPage.xaml.cs (code behind).

public partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
    }
}

You'll notice that we didn't create an instance of MainModel but rather we created a MainViewModel. This is the X in MVUX, it is a generated class that provides the glue between what XAML data bindings expect and the properties exposed by MainModel.

Feeds & Commands

In addition to the IState, sometimes we may need to create composite properties and execute commands. MVUX makes this simple with the IFeed and automatically detects public methods for commands. SimpleCalc will not make use of IFeed as it is not needed, for more information on this topic, be sure to check out the documentation: Using a FeedView.

The button inputs from the Calculator are handled via the Input method, which is exposed as an ICommand by MVUX.

With our UI updated, we can run the app again and press the buttons, resulting in a calculated output - We now have a functioning calculator.

Import UI from Figma or Creating the Layout | Next