Tutorial - Task Screen

Introduction

ViewModels can be used to provide bound properties for your view as well as logic for managing your data. This page creates a task screen which displays a list of tasks in a ListBox. The user can add and remove tasks using the UI. The logic for this behavior is in the bound view model.

Defining TaskScreenViewModel

The TaskScreenViewModel class contains all of the properties for our TaskScreen binding. Not only does it include properties for binding but it also provides methods for performing actions on these properties, such as adding or removing tasks.

public class TaskScreenViewModel : ViewModel
{
    public ObservableCollection<TaskItemViewModel> Tasks
    {
        get => Get<ObservableCollection<TaskItemViewModel>>();
        set => Set(value);
    }

    public TaskItemViewModel? SelectedTask
    {
        get => Get<TaskItemViewModel?>();
        set => Set(value);
    }

    public string NewTaskName
    {
        get => Get<string>();
        set => Set(value);
    }

    public TaskScreenViewModel()
    {
        Tasks = new ();
    }

    public void HandleAddTask()
    {
        if (!string.IsNullOrWhiteSpace(NewTaskName))
        {
            Tasks.Add(new TaskItemViewModel { Name = NewTaskName });
            NewTaskName = string.Empty;
        }
    }

    public void HandleRemoveTask()
    {
        if (SelectedTask != null)
        {
            Tasks.Remove(SelectedTask);
        }
    }
}

This view model includes an ObservableCollection property called Tasks. By making this inherit from ObservableCollection, a bound ListBox automatically updates its items whenever items are added or removed.

The ViewModel also includes methods for adding or removing tasks. These methods perform their own validation, using the ViewModel's properties to determine if actions can be performed.

The Tasks property gets assigned in the TaskScreenViewModel's constructor and doesn't change. This means that the property could have a private or init setter. This example creates a public setter to show that the entire collection could also be replaced and the binding ListBox would still update its items correctly.

Using the Get and Set methods on properties is recommended, even if the property itself is unlikely to change. By using Get and Set on a property of type ObservableCollection, other properties can still use a DependsOn attribute which references the Tasks property. For more information on using DependsOn, see the Binding Deep Dive page.

Each task is itself a view model, so we need to define the TaskItemViewModel. This example is simple so the TaskItemViewModel only includes a single property, but a more complex project may include a class with more properties.

Defining TaskScreen

This section shows how to set up binding in a TaskScreen class. The binding is the same whether you use the Gum UI tool or a code-only approach.

The TaskListBox and TaskNameTextBox bind to properties on the view model using the regular SetBinding call.

The TaskListBox sets its DisplayMemberPath to TaskItemViewModel.Name, resulting in the name of each item being displayed in the ListBoxItem. If this is not assigned, then each ListBoxItem displays the qualified class name of the ViewModel.

Finally, the two buttons have their Click events handled by calling the ViewModel's HandleAddTask and HandleRemoveTask methods.

Currently Gum does not support command binding. Future versions of Gum may introduce this feature, but in the meantime events must be manually subscribed and handled as shown in the code above.

Using the TaskScreen

Once the TaskScreen is defined, we can instantiate this in our game. The following code shows how to create a TaskScreen instance and assign its BindingContext to a TaskScreenViewModel instance.

Now we have a fully functional screen where tasks can be added and removed.

TaskScreen using bound properties to add and remove tasks

Last updated

Was this helpful?