У меня есть небольшой проект с двумя страницами, показывающими представление списка. Но одна из моих страниц не работает, несмотря на то, что это тот же код с небольшими изменениями (названия реквизитов). Контекст привязки берет нужную мне информацию (список пациентов), но страница возвращается пустой. На другой моей странице с тем же кодом Viewlist работает правильно. Может быть, я что-то упускаю или это может быть опечатка, я действительно не знаю, что происходит. Пожалуйста, помогите мне, и если у вас есть предложения по улучшению моего кода, скажите, что я новичок в формах xamarin.
XAML:
<ListView x:Name = "appointmentListView"
SeparatorVisibility = "None"
HasUnevenRows = "true"
ItemsSource = "{Binding Appointments}">
<ListView.Header>
<Grid BackgroundColor = "#03A9F4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "10"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "10"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height = "30"/>
<RowDefinition Height = "80"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "10"/>
</Grid.RowDefinitions>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding = "15,10" HorizontalOptions = "FillAndExpand" x:DataType = "model:Appointment">
<Label VerticalOptions = "FillAndExpand" VerticalTextAlignment = "Center"
Text = "{Binding Patient}"
FontSize = "24"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Код позади:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class AppointmentListViewDetail : ContentPage
{
public AppointmentListViewDetail()
{
InitializeComponent();
BindingContext = new AppointmentListViewModel();
appointmentListView.ItemSelected += (s, e) =>
{
if (e.SelectedItem as Appointment != null)
{
Action goToPage = async () =>
{
await PopupNavigation.Instance.PushAsync(new AppointmentDetailsPopup(e.SelectedItem as Appointment));
appointmentListView.SelectedItem = null;
};
goToPage.Invoke();
}
};
}
protected override void OnAppearing()
{
base.OnAppearing();
MessagingCenter.Subscribe<AppointmentListViewModel>(this, "Reload", (p) =>
{
BindingContext = p;
});
MessagingCenter.Subscribe<AppointmentFilterViewModel>(this, "Filter", (p) =>
{
string? nameFilter = p.NameFilter.Text;
DateTime? startDateFilter = DateTime.ParseExact(p.StartDateFilter.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
DateTime? finalDateFilter = DateTime.ParseExact(p.FinalDateFilter.Text, "dd/MM/yyyy", CultureInfo.InvariantCulture);
Status? statusFilter = (Status)Enum.Parse(typeof(Status), p.StatusFilter.Text);
BindingContext = new AppointmentListViewModel(nameFilter, startDateFilter, finalDateFilter, statusFilter);
});
}
ViewModel:
public class AppointmentListViewModel
{
ObservableCollection<Appointment> _appointments;
public ObservableCollection<Appointment> Appointments
{
get { return _appointments; }
set
{
_appointments = value;
OnPropertyChanged(nameof(Appointments));
}
}
public ICommand Filter { get; set; }
public AppointmentListViewModel()
{
var getAppointmentsList = new Action(async () =>
{
Appointments = new ObservableCollection<Appointment>(await Startup.ServiceProvider.GetService<AppointmentService>().ToListAsync());
});
getAppointmentsList.Invoke();
}
public AppointmentListViewModel(string? patient, DateTime? startDate, DateTime? finalDate, Status? status)
{
var getPatientList = new Action(async () =>
{
Appointments = new ObservableCollection<Appointment>(await Startup.ServiceProvider.GetService<AppointmentService>().FilterSearchAsync(patient, startDate, finalDate, status));
});
getPatientList.Invoke();
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Модель:
public class Appointment
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public float Price { get; set; }
public DateTime Date { get; set; }
public Status PaymentStatus { get; set; }
public string Patient { get; set; }
}
Вы пытались отладить это? Содержит ли ваша коллекция Appointments что-либо после вызова сеттера, если он когда-либо вызывается?
@Jason, спасибо за предположение, что проблема заключалась в том, как моя виртуальная машина загружала данные. Кстати, я отладил, но я не нашел ошибку, так что еще раз спасибо!
Если возможно, не могли бы вы создать Минимальный воспроизводимый пример по ссылке на репозиторий github?
Я решил эту проблему, используя Task.Run().Wait(), получается, что страница загружалась до получения данных. Спасибо всем!
Вы можете опубликовать свой идентификатор решения, которое вы выяснили, поскольку это полезно для других, столкнувшихся с той же проблемой. Спасибо!





Я решил эту проблему, используя Task.Run().Wait(). Я рекомендую использовать это, если вы пытаетесь получить данные из базы данных в вашей модели просмотра.
ViewModel:
public AppointmentListViewModel()
{
Task.Run(async () =>
{
Appointments = new ObservableCollection<Appointment>(await Startup.ServiceProvider.GetService<AppointmentService>().ToListAsync());
}).Wait();
}
Сервис, содержащий все операции, связанные с базой данных:
public AppointmentService()
{
string dbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "patient.db3");
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<Appointment>().Wait();
}
public Task<List<Appointment>> ToListAsync()
{
return _database.Table<Appointment>().ToListAsync();
}
попробуйте жестко закодировать
Appointmentsсписок тестовых данных и закомментировать весь остальной код, который загружает эти данные. Если это работает, значит, проблема в том, как ваша виртуальная машина загружает данные.