#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
в коде за тем же экземпляром yourAnnouncesViewModel
, над которым вы работаете в своем коде, он должен работать.
Ответ №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.