Данные привязки CollectionView не обновляются после запуска OnPropertyChanged

#c# #xaml #xamarin.forms #data-binding

#c# #xaml #xamarin.forms #привязка данных

Вопрос:

У меня есть CollectionView с привязкой ObservableCollection<Announce> Announces , которая правильно заполняется данными при появлении страницы. Затем я отправляю Post-запрос, создающий новый Announce, OnPropertyChanged вызывается метод Announces , обновляются данные как в announces , так и в, но средство получения не вызывается, и данные в CollectionView не обновляются. Должен ли получатель вызываться автоматически после OnPropertyChanged ? Чего мне не хватает в моем коде, который не обновляет пользовательский интерфейс?

AnnouncesService — это простая служба, которая возвращает наблюдаемые коллекции Announce из http-запросов. Вот моя AnnouncesViewModel:

  public class AnnouncesViewModel : INotifyPropertyChanged
    {
        ObservableCollection<Announce> announces;
        public ObservableCollection<Announce> Announces 
        {
            get => announces;
            set { announces = value; OnPropertyChanged("Announces"); } 
        }
        public AnnouncesService service;
        public event PropertyChangedEventHandler PropertyChanged;

        public AnnouncesViewModel()
        {
            service = new AnnouncesService();
            Announces = new ObservableCollection<Announce>();
            getAnnounces();
        }

        public async Task addAnnounce(Announce announce)
        {
            Announces = await service.PostAnnounceAsync(announce); //same as using getAnnounces again            
        }
       
        public async void getAnnounces()
        {
            Announces = await service.GetAnnouncesAsync();            
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

    }
  

Вот мой XAML с привязкой

  <ContentPage Title="">
        <ContentPage.BindingContext>
                <vm:AnnouncesViewModel/>
            </ContentPage.BindingContext>
        <ContentPage.Content>

            <CollectionView ItemsSource="{Binding Announces}"
                            SelectionMode="Single"
                            SelectionChanged="CollectionView_SelectionChanged">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Label Text="{Binding location}"/>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </ContentPage.Content>
    </ContentPage>
  

и страница с вкладками, которая вызывает AddAnnounce из AnnouncesViewModel

  public partial class TabbedPage1 : TabbedPage
    {
        private AnnouncesService service;
        private AnnouncesViewModel viewModel;
        public TabbedPage1()
        {
            InitializeComponent();
            service = new AnnouncesService();
            viewModel = new AnnouncesViewModel();
        }

        private async void AddAnnounce(object sender, EventArgs e)
        {
            Announce announce = new Announce(localtion_entry.Text,sport_entry.Text,1);
            await viewModel.addAnnounce(announce);
        }
}
  

Комментарии:

1. почему вы просто не добавляете новые данные в ObservableCollection вместо того, чтобы каждый раз создавать новый экземпляр ObservableCollection?

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

3. Похоже, что у каждой из ваших двух страниц есть свой собственный экземпляр виртуальной машины.

4. Как указал @Jason, вы, вероятно, используете 2 разных экземпляра вашего AnnouncesViewModel , созданного в xaml, привязанного к пользовательскому интерфейсу, но данные в нем не обновляются, а другой, созданный в коде, где данные обновляются, но не привязаны к пользовательскому интерфейсу.

5. Мы не знаем, как создаются ваши страницы и TabbedPage, но да, если вы назначаете BindingContext свой ContentPage в коде за тем же экземпляром your AnnouncesViewModel , над которым вы работаете в своем коде, он должен работать.

Ответ №1:

Итак, проблема заключалась в том, что я использовал 2 разных экземпляра AnnouncesViewModel . Один в XAML и один в cs-коде для вызова AddAnnounce . Чтобы исправить это, я удалил эту часть из своего кода XAML

 <ContentPage.BindingContext>
                <vm:AnnouncesViewModel/>
</ContentPage.BindingContext>
  

добавлен x:Name = "page" на мою страницу содержимого и присвоен BindingContext в конструкторе TabbedPage1:

 private AnnouncesViewModel viewModel;
public TabbedPage1()
{
    InitializeComponent();
    viewModel = new AnnouncesViewModel();
    page.BindingContext = viewModel;
}
  

Я также использую метод Add в AnnouncesViewModel для добавления содержимого в мою Announces ObservableCollection.