Louwrens Potgieter
Louwrens Potgieter

Reputation: 117

MVVM INotifyPropertyChanged not working

Please assist: I have implemented the MVVM design on a simple app using Xamarin. I have one Model (User) and one ViewModel (UserViewModel). Please note that this app is my first Xamarin/MVVM app and that I am new to this.

The issue that i have is that adding or removing a User, the View does NOT update. When I add or remove a user I can confirm that the Database is updated, but not my view.

Please see my code below, what am i missing?

User Model:

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsActive { get; set; }

    public List<Role> RolesList { get; set; }
}

UserViewModel Code:

public class UsersViewModel : INotifyPropertyChanged
        {
        private UserServices UserServ { get; set; }

        public User UserSelected { get; set; }

        private ObservableCollection<User> userList;
        public ObservableCollection<User> UserList
        {
            get
            {
                return userList;
            }
            set
            {
                if (userList != value)
                {
                    userList = value;
                    NotifyPropertyChanged();
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        public UsersViewModel()
        {
            UserServ = new UserServices();
            UsersLoadAsync();
        }

        public async void UsersLoadAsync()
        {
            UserList = await UserServ.UsersGetAsync();
        }
    }

User Helper Service code (Added for completeness)

public class UserServices
    {

        public async Task<ObservableCollection<User>> UsersGetAsync()
        {
            ObservableCollection<User> UserList = await App.UserService.GetAsync();

            return UserList;
        }

        public async Task<bool> UsersAddAsync(User user)
        {
            bool success = await App.UserService.PostAsync(user);
            return success;
        }

        public async Task<bool> UsersRemoveAsync(User user)
        {
            bool success = await App.UserService.DeleteAsync(user.Id, user);
            return success;
        }

    }

View Xaml Code:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:PB_Logbook"
             x:Class="PB_Logbook.MainPage"
             xmlns:ViewModels="clr-namespace:PB_Logbook.ViewModels;assembly:PB_Logbook">

    <ContentPage.BindingContext>
        <ViewModels:UsersViewModel/>
    </ContentPage.BindingContext>
    <StackLayout>
        <ListView ItemsSource="{Binding UserList, Mode=TwoWay}" HasUnevenRows="True" ItemSelected="Item_SelectedAsync" IsPullToRefreshEnabled="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Vertical" Padding="12,6">
                        <Label Text="{Binding Username}" FontSize="24"/>
                        <Label Text="{Binding FirstName}" FontSize="18" Opacity="0.6"/>
                        <Label Text="{Binding LastName}" FontSize="18" Opacity="0.6"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <Button Text="Add" Clicked="AddButton_ClickedAsync"></Button>
        <Button Text="Remove" Clicked="RemoveButton_ClickedAsync"></Button>
    </StackLayout>


</ContentPage>

View code behind:

public partial class MainPage : ContentPage
    {
        private UserServices UserServices { get; set; }
        private UsersViewModel UsersVM { get; set; }


        public MainPage()
        {
            InitializeComponent();
            UserServices = new UserServices();
            UsersVM = new UsersViewModel();
        }

        private async void AddButton_ClickedAsync(object sender, EventArgs e)
        {
            await AddUserAsync();
        }

        private async void RemoveButton_ClickedAsync(object sender, EventArgs e)
        {
            await RemoveUserAsync();
        }

        private async void Item_SelectedAsync(object sender, EventArgs e)
        {
            UsersVM.UserSelected = ((User)((ListView)sender).SelectedItem);

        }

        private async void Pull_RefreshAsync(object sender, EventArgs e)
        {
            //UsersVM.UsersLoadAsync();
        }

        private async Task AddUserAsync()
        {
            Random rnd = new Random();
            int rndNumber = rnd.Next(1, 100);

            User user = new User()
            {
                Username = "User  " + rndNumber,
                FirstName = "Firstname  " + rndNumber,
                LastName = "Surname " + rndNumber,
                IsActive = true
            };

            bool success = await UserServices.UsersAddAsync(user);

            if (success)
            {
                if (!UsersVM.UserList.Contains(user))
                    UsersVM.UserList.Add(user);
            }
        }

        private async Task RemoveUserAsync()
        {
            bool success = await UserServices.UsersRemoveAsync(UsersVM.UserSelected);

            if (success)
            {
                if (UsersVM.UserList.Contains(UsersVM.UserSelected))
                    UsersVM.UserList.Remove(UsersVM.UserSelected);
            }
        }
    }

The issue is with adding/removing users that does not update in my view.

Thank you.

Upvotes: 0

Views: 1147

Answers (1)

mark333...333...333
mark333...333...333

Reputation: 1360

If you're new to Xamarin MVVM, this link will help you understand the basics of MVVM in Xamarin Forms

https://deanilvincent.github.io/2017/06/03/basic-understanding-of-mvvm-and-databinding-in-xamarin-forms/

I would suggest as well, please lessen your behind the codes and just implement everything including the commands in your ViewModel.

You've written that your codes are working when saving and updating but not reflecting the view right? You should put your method in fetching the list right after your save command.

Like this in your xaml

<Button Text="Save" Command="{Binding SaveCommand}"/>

In your ViewModel, you should use Command from Xamarin

public Command SaveCommand{
   get{
      return new Command(async()=>{
           // your command save here
           // then put your method for fetching the updated list: your UsersLoadAsync();
      });
   }
}

If you're new to MVVM, you can also check this link. It uses Xamarin MVVM. When you finish, you'll have simple weather app with simple mvvm implementations

I hope it helps you

Upvotes: 2

Related Questions