I'm experiencing a problem with my Maui App. I'm trying to bind an Application.Score to a label and the value is not refreshing, even though I'm seeing the value refreshing in the viewModel.
Here you can find my xaml page:
<?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:model="clr-namespace:FAZSO.Model"
xmlns:viewmodel="clr-namespace:FAZSO.ViewModel"
x:Class="FAZSO.MainPage"
Title="FAZSO"
x:DataType="viewmodel:MainPageViewModel">
<VerticalStackLayout Margin="0,52,0,0" Spacing="20">
<Grid Padding="5" HorizontalOptions="FillAndExpand">
<Label Text="FAZ SÓ!"
FontSize="26"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand" />
<Label Text="{Binding ApplicationPlayer.Score}"
FontSize="26"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand" />
</Grid>
<CollectionView ItemsSource="{Binding Habits}" SelectionMode="None" ItemsLayout="VerticalGrid, 2">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Habit">
<Grid Padding="5" HorizontalOptions="FillAndExpand">
<Frame HeightRequest="150" WidthRequest="160" Style="{StaticResource CardView}" Margin="10">
<VerticalStackLayout BackgroundColor="{Binding ButtonColor}" Margin="-1">
<Image Source="achievement.svg" WidthRequest="100" HeightRequest="100" Margin="-10" />
<Label Margin="0" Text="{Binding Name}" FontSize="Medium" TextColor="WhiteSmoke" WidthRequest="100" HeightRequest="50" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" />
</VerticalStackLayout>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainPageViewModel}}, Path=ExecuteButtonCommand}"
CommandParameter="{Binding .}" />
</Frame.GestureRecognizers>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
and here you can find my viewModel:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FAZSO.ViewModel;
using System.ComponentModel;
using System.Diagnostics;
namespace FAZSO.ViewModel;
[QueryProperty(nameof(ApplicationPlayer), "applicationPlayer")]
public partial class MainPageViewModel : BaseViewModel
{
[ObservableProperty]
Player applicationPlayer = new();
public ObservableCollection<Habit> Habits { get; set; } = new();
public MainPageViewModel()
{
Title = "FAZ SO";
Player player1 = new Player();
player1.Name = "Player1";
applicationPlayer = player1;
Habit habit = new()
{
ID = 1,
Name = "Ler",
Type = "Mandatory",
ButtonColor = Color.FromRgb(71, 8, 178),
};
Habit habit1 = new()
{
ID = 2,
Name = "Exercício",
Type = "Mandatory",
ButtonColor = Color.FromRgb(71, 8, 178),
};
Habit habit2 = new()
{
ID = 3,
Name = "Tocar Guitarra",
Type = "Mandatory",
ButtonColor = Color.FromRgb(71, 8, 178),
};
Habit habit5 = new()
{
ID = 4,
Name = "Ler Artigo",
Type = "Mandatory",
ButtonColor = Color.FromRgb(71, 8, 178),
};
Habit habit6 = new()
{
ID = 5,
Name = "Correr",
Type = "Optional",
ButtonColor = Color.FromRgb(128, 128, 128),
};
Habit habit7 = new()
{
ID = 6,
Name = "Codar",
Type = "Optional",
ButtonColor = Color.FromRgb(128, 128, 128),
};
Habits.Add(habit);
Habits.Add(habit1);
Habits.Add(habit2);
Habits.Add(habit5);
Habits.Add(habit6);
Habits.Add(habit7);
applicationPlayer.Habits = Habits.ToList();
}
[RelayCommand]
public async Task ExecuteButton(Habit habit)
{
try
{
habit.Name = "Done";
habit.ButtonColor = Color.FromRgb(0, 177, 64);
ApplicationPlayer.Score += 1;
var index = Habits.IndexOf(Habits.FirstOrDefault(x => x.ID == habit.ID));
Habits[index] = habit;
}
catch (Exception ex)
{
await Shell.Current.DisplayAlert("Error!", ex.Message, "OK");
}
}
}
Do you have any tip why this is not working?
just for reference, this is my Player class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FAZSO.Model
{
public class Player
{
public List<Habit> Habits { get; set; }
public string Name { get; set; }
public int Score { get; set; }
}
}
Thanks
I've tried to debug this problem using debug mode in viewModel. I can see the value refreshing but not in the xaml page
As Jason said that inherit Player from ObservableObject
:
public class Player : ObservableObject
{
public List<Habit> Habits { get; set; }
public string Name { get; set; }
public int Score { get; set; }
}
In additon, you can also add an If statement to determine whether the habit has been clicked, and if so, return directly:
public async Task ExecuteButton(Habit habit)
{
try
{
if (habit.Name == "Done")
{
return;
}
habit.Name = "Done";
habit.ButtonColor = Color.FromRgb(0, 177, 64);
ApplicationPlayer.Score += 1;
....
}