Я новичок в .NET MAUI/MVVM/SQLite и C#, если уж на то пошло. Я пытаюсь использовать свою ViewModel для привязки данных из моего класса модели. Я могу прекрасно использовать пространство имен модели в качестве свойства привязки, и оно отображает данные в моем списке. Однако как только я пытаюсь использовать свою ViewModel, она больше не отображается.
CRUDView XAML работает
<Frame Grid.Row = "6" Grid.Column = "1" Grid.ColumnSpan = "3" BackgroundColor = "#B1C0C9" BorderColor = "#7989A3">
<ScrollView Orientation = "Vertical">
<ListView x:Name = "listView"
BackgroundColor = "Gray"
HasUnevenRows = "True"
SeparatorVisibility = "Default"
ItemTapped = "listView_ItemTapped"
FlexLayout.Grow = "1"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<VerticalStackLayout Padding = "5">
<Label Text = "{Binding Question}"
FontSize = "17"
FontFamily = "OCRA"
TextColor = "Black"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "50"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<Label Text = "{Binding Id}"
FontSize = "10"
FontFamily = "OCRA"
TextColor = "Black"
Grid.Column = "0"
/>
<Label Text = "{Binding Answer}"
FontSize = "15"
FontFamily = "OCRA"
TextColor = "White"
Grid.Column = "1"
Padding = "10"/>
<Label Text = "{Binding Difficulty}"
FontSize = "15"
FontFamily = "OCRA"
TextColor = "Black"
Grid.Column = "3"
Padding = "10"/>
</Grid>
</VerticalStackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</Frame>
Когда я вернусь к использованию ViewModel для привязки данных:
CRUDView XAML
<Frame Grid.Row = "6" Grid.Column = "1" Grid.ColumnSpan = "3" BackgroundColor = "#B1C0C9" BorderColor = "#7989A3">
<ScrollView Orientation = "Vertical">
<ListView x:Name = "listView"
BackgroundColor = "Gray"
HasUnevenRows = "True"
SeparatorVisibility = "Default"
ItemTapped = "listView_ItemTapped"
FlexLayout.Grow = "1"
ItemsSource = "{Binding Flashcards}">
<ListView.ItemTemplate>
<DataTemplate x:DataType = "vm:CRUDViewModel">
<ViewCell>
<VerticalStackLayout Padding = "5">
<Label Text = "{Binding Flashcard.Question}"
FontSize = "17"
FontFamily = "OCRA"
TextColor = "Black"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "50"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<Label Text = "{Binding Flashcard.Id}"
FontSize = "10"
FontFamily = "OCRA"
TextColor = "Black"
Grid.Column = "0"
/>
<Label Text = "{Binding Flashcard.Answer}"
FontSize = "15"
FontFamily = "OCRA"
TextColor = "White"
Grid.Column = "1"
Padding = "10"/>
<Label Text = "{Binding Flashcard.Difficulty}"
FontSize = "15"
FontFamily = "OCRA"
TextColor = "Black"
Grid.Column = "3"
Padding = "10"/>
</Grid>
</VerticalStackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollView>
</Frame>
Модель представления
namespace cadflash.ViewModels
{
public partial class CRUDViewModel : ObservableObject
{
[ObservableProperty]
public ObservableCollection<Flashcard> flashcards = new();
[ObservableProperty]
public Flashcard flashcard = new();
public CRUDViewModel()
{
Flashcard = new Flashcard();
Flashcards = [];
}
МауиПрограмма
MauiProgram
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
fonts.AddFont("OCRAEXT.ttf", "OCRA");
});
builder.Services.AddSingleton<LocalDbService>();
builder.Services.AddTransient<HomeView>();
builder.Services.AddTransient<DifficultyView>();
builder.Services.AddTransient<CRUDView>();
builder.Services.AddTransient<CRUDViewModel>();
builder.Services.AddTransient<DifficultyViewModel>();
builder.Services.AddTransient<HomeViewModel>();
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
}
CRUDView.cs
CRUDView.xaml.cs
public partial class CRUDView : ContentPage
{
CRUDViewModel viewModel;
private readonly LocalDbService localDbService; // This is the service that is used to interact with the local database
private int _editFlashcardId; // This is the ID of the flashcard that is being edited
public CRUDView(LocalDbService localDbService)
{
InitializeComponent();
BindingContext = new CRUDViewModel();
this.localDbService = localDbService;
Task.Run(async () => await localDbService.GetFlashcardsAsync());
}
protected override async void OnAppearing()
{
base.OnAppearing();
listView.ItemsSource = await localDbService.GetFlashcardsAsync();
}
Это была неделя мучительной боли в попытках отобразить данные в списке. Сегодня я придумал, как просто привязать данные непосредственно из класса модели. В идеале я хотел бы использовать привязку ViewModel...
@Jason Что мне нужно сделать на виртуальной машине, чтобы инициализировать список Flashcard для уже заполненной базы данных SQLite?
что-то вроде Flashcards = await localDbService.GetFlashcardsAsync();





Есть некоторые проблемы с использованием в вашем коде.
Во-первых, поскольку вы пытались использовать MVVM, вам необходимо добавить соответствующий код localDbService в вашу модель MVVM. Например, вы можете добавить в модель MVVM метод localDbService и загрузку данных.
//private readonly LocalDbService localDbService; // This is the service that is used to interact with the local database
public CRUDViewModel()
{
//initialize localDbService and load data
//this.localDbService = localDbService;
}
Во-вторых, поскольку вы установили ItemsSource = "{Binding Flashcards}" для своего ListView, тип данных DataTemplate ListView должен быть Flashcard, а не <DataTemplate x:DataType = "vm:CRUDViewModel">.
В-третьих, удалите префикс Flashcard при привязке (например, <Label Text = "{Binding Flashcard.Id}").
Я достиг этой функции с некоторыми поддельными данными.
Вы можете обратиться к следующему коду:
CRUDViewModel.cs
public partial class CRUDViewModel:ObservableObject
{
[ObservableProperty]
public ObservableCollection<Flashcard> flashcards = new();
[ObservableProperty]
public Flashcard flashcard = new();
//private readonly LocalDbService localDbService; // This is the service that is used to interact with the local database
public CRUDViewModel()
{
Flashcard = new Flashcard();
Flashcards = [];
//initialize localDbService and load data
//this.localDbService = localDbService;
GetData();
}
public async void GetData() {
//List<Flashcard> datas = await localDbService.GetFlashcardsAsync());
// add the data to Flashcards
//foreach (Flashcard flashcard in datas) {
// Flashcards.Add(flashcard);
//}
//add some fake data to variable Flashcards
Flashcards.Add(new Flashcard { Id = 01, Question = "1+ 1 = ", Answer = "2", Difficulty = "easy" });
Flashcards.Add(new Flashcard { Id = 02, Question = "1+ 3 = ", Answer = "4", Difficulty = "easy" });
Flashcards.Add(new Flashcard { Id = 03, Question = "123+163 = ", Answer = "286", Difficulty = "difficult" });
}
}
MainPage.xaml
<?xml version = "1.0" encoding = "utf-8" ?>
<ContentPage xmlns = "http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x = "http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:models = "clr-namespace:MauiMvvmListApp0407.Models"
x:Class = "MauiMvvmListApp0407.MainPage">
<Frame Grid.Row = "6" Grid.Column = "1" Grid.ColumnSpan = "3" BackgroundColor = "#B1C0C9" BorderColor = "#7989A3">
<ListView x:Name = "listView"
BackgroundColor = "Gray"
HasUnevenRows = "True"
SeparatorVisibility = "Default"
ItemsSource = "{Binding Flashcards}">
<ListView.ItemTemplate>
<DataTemplate x:DataType = "models:Flashcard">
<ViewCell>
<VerticalStackLayout Padding = "5">
<Label Text = "{Binding Question}"
FontSize = "17"
FontFamily = "OCRA"
TextColor = "Black"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "50"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<Label Text = "{Binding Id}"
FontSize = "10"
FontFamily = "OCRA"
TextColor = "Black"
Grid.Column = "0"
/>
<Label Text = "{Binding Answer}"
FontSize = "15"
FontFamily = "OCRA"
TextColor = "White"
Grid.Column = "1"
Padding = "10"/>
<Label Text = "{Binding Difficulty}"
FontSize = "15"
FontFamily = "OCRA"
TextColor = "Black"
Grid.Column = "3"
Padding = "10"/>
</Grid>
</VerticalStackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Frame>
</ContentPage>
MainPage.xaml.cs
public partial class MainPage : ContentPage
{
CRUDViewModel viewModel;
public MainPage()
{
InitializeComponent();
viewModel = new CRUDViewModel();
this.BindingContext = viewModel;
}
}
Большое спасибо! Изменение DataTemplate на model:Flashcard решило проблему. Я также воспользовался вашим советом и включил другие предложенные изменения.
во-первых, вы назначаете
ItemsSourceкак в XAML, так и в коде. Выбирайте одно или другое, а не оба. Во-вторых, в вашей виртуальной машине вы инициализируетеFlashCardsв пустой список и никогда не добавляете в него какие-либо данные.