MVVM INotifyPropertyChanged не работает

Пожалуйста, помогите: я реализовал дизайн MVVM в простом приложении с помощью Xamarin. У меня есть одна модель (пользователь) и одна ViewModel (UserViewModel). Обратите внимание, что это приложение — мое первое приложение Xamarin/MVVM, и я новичок в этом.

У меня проблема в том, что при добавлении или удалении пользователя представление НЕ обновляется. Когда я добавляю или удаляю пользователя, я могу подтвердить, что обновляется база данных, но не мое представление.

Пожалуйста, посмотрите мой код ниже, что мне не хватает?

Модель пользователя:

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:

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();
        }
    }

Код вспомогательной службы пользователя (добавлен для полноты картины)

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;
        }

    }

Просмотр Xaml-кода:

<?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>

Посмотреть код позади:

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);
            }
        }
    }

Проблема заключается в добавлении/удалении пользователей, которые, на мой взгляд, не обновляются.

Спасибо.


person Louwrens Potgieter    schedule 08.10.2017    source источник
comment
Замените List<> и вашу реализацию INotifyPropertyChanged на ObservableCollection<>.   -  person jsanalytics    schedule 08.10.2017
comment
Спасибо за ответ, @jstreet. Я заменил List‹› на ObservableCollection‹›, но все равно не работает. Любой другой совет?   -  person Louwrens Potgieter    schedule 08.10.2017
comment
Я посмотрю повнимательнее, как только у меня будет возможность.   -  person jsanalytics    schedule 08.10.2017
comment
Что такое App.UserService? Вам необходимо опубликовать MCVE.   -  person jsanalytics    schedule 08.10.2017
comment
Итак, у вас есть UserServices и App.UserService, и, по-видимому, ни один из них на самом деле не обновляет UsersViewModel.   -  person jsanalytics    schedule 08.10.2017


Ответы (1)


Если вы не знакомы с Xamarin MVVM, эта ссылка поможет вам понять основы MVVM в Xamarin Forms.

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

Я бы также предложил, пожалуйста, уменьшите количество кодов и просто реализуйте все, включая команды в вашей ViewModel.

Вы написали, что ваши коды работают при сохранении и обновлении, но не отражают представление, верно? Вы должны указать свой метод получения списка сразу после команды сохранения.

Как это в вашем xaml

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

В вашей ViewModel вы должны использовать команду из Xamarin

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

Если вы новичок в MVVM, вы также можете проверить это ссылка. Он использует Xamarin MVVM. Когда вы закончите, у вас будет простое приложение погоды с простой реализацией mvvm.

Я надеюсь, что это поможет вам

person mark333...333...333    schedule 08.10.2017
comment
Спасибо вам за публикацию. Я последовал вашему совету и перенес всю свою логику и команды в ViewModel. Я также попытался перезагрузить список «Пользователь» снова после сохранения, но он по-прежнему не обновляет представление. - person Louwrens Potgieter; 08.10.2017