The ViewModel should only decide whether it is busy, and the decision about what cursor to use, or whether to use some other technique such as a progress bar should be left up to the View.
And on the other hand, handling it with code-behind in the View is not so desirable either, because the ideal is that Views should not have code-behind.
Therefore I chose to make a class that can be used in the View XAML to specify that the cursor should be change to Wait when the ViewModel is busy. Using UWP + Prism the class definition is:
public class CursorBusy : FrameworkElement
{
private static CoreCursor _arrow = new CoreCursor(CoreCursorType.Arrow, 0);
private static CoreCursor _wait = new CoreCursor(CoreCursorType.Wait, 0);
public static readonly DependencyProperty IsWaitCursorProperty =
DependencyProperty.Register(
"IsWaitCursor",
typeof(bool),
typeof(CursorBusy),
new PropertyMetadata(false, OnIsWaitCursorChanged)
);
public bool IsWaitCursor
{
get { return (bool)GetValue(IsWaitCursorProperty); }
set { SetValue(IsWaitCursorProperty, value); }
}
private static void OnIsWaitCursorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
CursorBusy cb = (CursorBusy)d;
Window.Current.CoreWindow.PointerCursor = (bool)e.NewValue ? _wait : _arrow;
}
}
And the way to use it is:
<mvvm:SessionStateAwarePage
x:Class="Orsa.Views.ImportPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mvvm="using:Prism.Windows.Mvvm"
xmlns:local="using:Orsa"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mvvm:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.RowDefinitions>
.
.
</Grid.RowDefinitions>
<local:CursorBusy IsWaitCursor="{Binding IsBusy}"/>
(other UI Elements)
.
.
</Grid>
</mvvm:SessionStateAwarePage>