Я новичок в MAUI, и у меня есть рабочий проект, который использует базу данных sqlite для хранения моих данных для моего проекта. Я пытаюсь внедрить объект доступа к базе данных в ViewModel для одной из моих страниц содержимого. Раньше у меня это работало, просто создавая («обновляя») мой объект доступа к базе данных, и база данных и проект работали нормально. Когда я изменил это, чтобы внедрить объект доступа к базе данных в конструктор ViewModel, я получаю сообщение об ошибке:
/Users/RemoteCommand/Projects/Notes/Views/AllNotesPage.xaml(9,9): Error: XLS0507: Type 'AllNotes' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter. (Notes) IntelliSense
Вот мой файл 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:Notes.Models"
x:Class = "Notes.Views.AllNotesPage"
Title = "AllNotesPage">
<ContentPage.BindingContext>
<models:AllNotes />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<!--<ToolbarItem Text = "Add" Clicked = "Add_Clicked" IconImageSource = "{FontImage Glyph='+', Color=White, Size=22}"/>-->
<ToolbarItem Text = "Add" Command = "{Binding AddClickedCommand}" IconImageSource = "{FontImage Glyph='+', Color=White, Size=22}"/>
</ContentPage.ToolbarItems>
<CollectionView x:Name = "notesCollection"
ItemsSource = "{Binding Notes}"
Margin = "20"
SelectionMode = "Single"
SelectionChanged = "notesCollection_SelectionChanged">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation = "Vertical" ItemSpacing = "10"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text = "{Binding Text}" FontSize = "22"/>
<Label Text = "{Binding Date}" FontSize = "14" TextColor = "Silver"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
Вот мой код:
namespace Notes.Views;
using Notes.Models;
using Notes.Views;
using Notes.Data;
using CommunityToolkit.Mvvm.Input;
public partial class AllNotesPage : ContentPage
{
public AllNotesPage()
{
InitializeComponent();
}
async void notesCollection_SelectionChanged(System.Object sender, Microsoft.Maui.Controls.SelectionChangedEventArgs e)
{
if (e.CurrentSelection.Count != 0)
{
var note = (Note)e.CurrentSelection[0];
await Shell.Current.GoToAsync($"{nameof(NotePage)}?{nameof(NotePage.ItemId)} = {note.ID}");
}
}
}
Вот моя ViewModel:
using System;
using System.Collections.ObjectModel;
using Notes.Data;
using Notes.Views;
using CommunityToolkit.Mvvm;
using CommunityToolkit.Mvvm.Input;
namespace Notes.Models;
public partial class AllNotes
{
NotesDatabase _notesDatabase;
public ObservableCollection<Note> Notes { get; set; } = new ObservableCollection<Note>();
public AllNotes(NotesDatabase notesDatabase)
{
_notesDatabase = notesDatabase;
LoadNotes();
}
[RelayCommand]
async void AddClicked()
{
await Shell.Current.GoToAsync(nameof(NotePage));
}
public async void LoadNotes()
{
Notes.Clear();
List<Note> notes = await _notesDatabase.GetItemsAsync();
foreach(Note note in notes)
{
Notes.Add(note);
}
}
}
и вот моя программа MauiProgram, в которой я определяю внедрение зависимостей:
using Microsoft.Extensions.Logging;
using Notes.Views;
using Notes.Models;
using Notes.Data;
namespace Notes;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
builder.Services.AddSingleton<AllNotes>();
builder.Services.AddSingleton<AllNotesPage>();
builder.Services.AddSingleton<NotesDatabase>();
return builder.Build();
}
}
[Примечание: я переключил AddSingleton на Add Transient для этой страницы для этих определений, чтобы посмотреть, решит ли это проблему, но это не так]
Я пробовал очень простую инъекцию зависимостей в более раннем тестовом проекте, где я ввел свой объект доступа к данным в код позади, и я получил ту же ошибку об отсутствии конструктора без параметров, и оказалось, что мне не хватало определения моего объекта доступа к данным И ContentPage как Transient или Singleton в MauiProgram (именно поэтому для этого проекта я добавил объект доступа к данным, ContentPage и ViewModel как Singletons в MauiProgram). Как только я это сделал, это сработало, но теперь, когда я использую ViewModel, которую я связываю в XAML, я не могу заставить DI работать для ViewModel.
Пожалуйста, помогите этому новичку!
Искренне,





Выполнение этого в XAML является открытым вопросом: Разрешить XAML BindingContext из ServiceCollection.
На данный момент сделайте это с помощью конструктора кода с параметром:
public AllNotesPage(AllNotes vm)
{
InitializeComponent();
BindingContext = vm;
}
DI введет vm, создав необходимый экземпляр AllNotes и его базы данных NotesDatabase.