Home > Software engineering >  XAML binding to model not updating UI
XAML binding to model not updating UI

Time:12-08

I am new to .Net Maui. I have follow James Montemagno's video tuorial: https://www.youtube.com/watch?v=ddmZ6k1GIkM&list=PLdo4fOcmZ0oUBAdL2NwBpDs32zwGqb9DY&index=6 on navigating between pages. I can successfully navigate from one page to the next and also send a complex data object as a parameter. However, on the new page, I want to use the parameter to fetch objects via a webservice in my ViewModel, and bind the xaml to the newly fetched objects. At first I tried this in the ViewModels' constructor, but the parameters where still null inside the constructor. I then invoked an event that fired when the property I am binding to changes partial void OnLoginResultChanged(LoginResult value). From there I call an async Task to fetch the objects from the webservice and try and bind and display them in the xaml. Unfortunately, I am not getting anything to show in the xaml.

Here is my code: ViewModel:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using MealPacApp.Model;

namespace MealPacApp.ViewModel
{
    [QueryProperty(nameof(Model.LoginResult), "LoginResult")]


    public partial class MainViewModel : ObservableObject
    {
        IConnectivity connectivity;
        Services.MealPacService mealPacService;

        [ObservableProperty]
        Model.User user = new();              

        [ObservableProperty]
        Model.LoginResult loginResult;

        partial void OnLoginResultChanged(LoginResult value)
        {
            this.GetDataForViewCommand.ExecuteAsync(null);
        }

        public MainViewModel(IConnectivity connectivity, Services.MealPacService mealPacService)
        {
            this.connectivity = connectivity;
            this.mealPacService = mealPacService;

            //Now check to see if there is internet connectivity
            if (connectivity.NetworkAccess != NetworkAccess.Internet)
            {
                Shell.Current.DisplayAlert("Oops!", "No internet is available. Please ensure you have an internet connection before continuing.", "OK");
                return;
            }
        }

        [RelayCommand]
        async Task GetDataForView()
        {
            try
            {
                if (loginResult != null)
                {
                    //Its not empty, so login here
                    var incmoingUser = await Services.MealPacService.GetUser(loginResult.Reference, loginResult.OrganisationId);
                    if (incmoingUser != null)
                    {
                        user = incmoingUser;
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }   
    }
}

Here is the View (Xaml):

<?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"
             x:Class="MealPacApp.MainPage"
             Title="Home"
             xmlns:viewmodel="clr-namespace:MealPacApp.ViewModel"
             xmlns:model="clr-namespace:MealPacApp.Model"
             x:DataType="viewmodel:MainViewModel">

      
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">          

            <Label
                Text="{Binding User.Name}"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />           

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

Here is the Model I am trying to bind too:

namespace MealPacApp.Model
{

    public partial class User
    {
        public int Userid { get; set; }
        public string Reference { get; set; }
        public string Name { get; set; }
    }
}

Here is my page code behind:

using MealPacApp.ViewModel;

namespace MealPacApp
{
    public partial class MainPage : ContentPage
    {
        public MainPage(MainViewModel vm)
        {
            InitializeComponent();
            BindingContext = vm;
        }
    }
}

As mentioned, the navigation is working, I am just missing how to get the property change to reflect in the Xaml. I have kept the [ObservableProperty] instead of implementing INotifyPropertyChanged as to my understanding, it takes care of the boiler plate stuff. Thanks in advance.

CodePudding user response:

This line

user = incmoingUser;

Is updating the private field user

You want to update the public property User which is observable

User = incmoingUser;
  • Related