我是 .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 进行数据绑定时:
CRUD查看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 绑定...
您的代码中的用法存在一些问题。
首先,由于您尝试使用MVVM,因此您需要将
localDbService
的相关代码添加到您的MVVM模型中。例如,您可以将 localDbService
和加载数据方法添加到 MVVM 模型。
//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
,那么ListView的DataTemplate
的数据类型应该是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" });
}
}
主页.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;
}
}