I am working on a tiny addition of a project using the MVVM pattern.
The project is a little bit bigger, but I stripped it down to a tiny sample project to make stuff easier here.
using CommunityToolkit.Mvvm.ComponentModel;
namespace MauiApp6.ViewModels
{
public partial class BusyViewModel : ObservableObject
{
[ObservableProperty]
private bool isBusy = false;
}
}
using CommunityToolkit.Mvvm.Input;
namespace MauiApp6.ViewModels
{
public partial class CommandViewModel
{
private BusyViewModel busyViewModel;
public CommandViewModel()
{
// Initialize BusyViewModel
busyViewModel = new BusyViewModel();
}
[RelayCommand()]
internal void Click()
{
// Set IsBusy to true
busyViewModel.IsBusy = true;
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MauiApp6.ViewModels"
x:Class="MauiApp6.MainPage" >
<StackLayout>
<Button Text="Click Me"
BindingContext="{Binding Source={vm:CommandViewModel}}"
Command="{Binding ClickCommand}"/>
<Label BindingContext="{Binding Source={vm:BusyViewModel}}"
Text="{Binding IsBusy}"/>
<ActivityIndicator BindingContext="{Binding Source={vm:BusyViewModel}}"
IsRunning="{Binding IsBusy}"/>
</StackLayout>
</ContentPage>
The problem is you have two BusyViewModel
instances, the view model you created for the Label and the view model embedded in the CommandViewModel
.
the ClickCommand
changes in the one embedded in the CommandViewModel, and it does not change in the BusyViewModel of the label so no visible change will happen.
the solution is as @Liyun Zang - MSFT suggested, you should make one instance of the CommandViewModel
and set the command of the button to this instance's ClickCommand
property. and set the 'BindingContext' label of the Label
and the ActivityIndicator
to this instance's BusyViewModel
property
public MainPage()
{
InitializeComponent();
// instance will be set to all the elements inside MainPage
BindingContext= new CommandViewModel();
}
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MauiApp6.ViewModels"
x:Class="MauiApp6.MainPage" >
<StackLayout>
<!--because BindingContext is set for the MainPage no need set it here again and setting it again here will lead to unexpected behaviour-->
<Button Text="Click Me"
Command="{Binding ClickCommand}"/>
<!--here BindingContext will be set to CommandViewModel.BusyViewModel property-->
<Label BindingContext="{Binding BusyViewModel}"
Text="{Binding IsBusy}"/>
<!--same thing-->
<ActivityIndicator BindingContext="{Binding Source={vm:BusyViewModel}}"
IsRunning="{Binding IsBusy}"/>
</StackLayout>
</ContentPage>