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 we need to replace the temporary DataContext class we created earlier. It's also important to note here that we will not initialize the MainModel since we need the X in MVUX. For this, we will use the generated MainViewModel class. You can do a Find/Replace to replace all references to TempDataContext with MainViewModel, and then remove the TempDataContext class.

public MainPage()
{
    this.DataContext(new MainViewModel(), (page, vm) => page
      .Content(...));
}

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