Reputation: 527
I'm new to C# and the .NET MAUI architecture. I'm trying to use a local SQLite database for a simple voter application.
VoterListPageView
is the Main Page that AppShell points to (code added below).
The following code keeps giving me this error:
System.MissingMethodException: 'No parameterless constructor defined for type 'VoterApp001.Views.VotersListPageView'.'
VotersListPageView.xaml.cs
using VoterApp001.ViewModels;
namespace VoterApp001.Views;
public partial class VotersListPageView : ContentPage
{
private VotersListPageViewModel _viewModel;
public VotersListPageView(VotersListPageViewModel viewModel) // <-- FAILS
//public VotersListPageView() // <-- WORKS IF I COMMENT OUT RELATED LINES BELOW
{
InitializeComponent();
_viewModel = viewModel;
this.BindingContext = _viewModel;
}
protected override void OnAppearing()
{
base.OnAppearing();
_viewModel.GetVotersListCommand.Execute(null);
}
}
The problem seems to be here:
public VotersListPageView(VotersListPageViewModel viewModel) // <-- FAILS
public VotersListPageView() // <-- WORKS IF I COMMENT OUT OTHER RELATED LINES BELOW
I need to pass-in my ViewModel, but the error is preventing me from doing that. What am I doing wrong?
VotersListPageViewModel.cs
sing CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;
using VoterApp001;
using VoterApp001.Models;
using VoterApp001.Services;
using VoterApp001.Views;
namespace VoterApp001.ViewModels
{
public partial class VotersListPageViewModel : ObservableObject
{
public ObservableCollection<VoterModel> VotersList { get; set; } = new ObservableCollection<VoterModel>();
private readonly IVoterService _voterService;
public VotersListPageViewModel(IVoterService voterService)
{
_voterService = voterService;
}
[RelayCommand]
public async void GetVotersList()
{
VotersList.Clear();
var votersList = await _voterService.GetVotersList();
if (votersList?.Count > 0)
{
votersList = votersList.OrderBy(f => f.FullName).ToList();
foreach (var voter in votersList)
{
votersList.Add(voter);
}
}
}
}
}
AppShell.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="VoterApp001.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:VoterApp001"
xmlns:views="clr-namespace:VoterApp001.Views"
Shell.FlyoutBehavior="Disabled">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate views:VotersListPageView}"
Route="MainPage" />
</Shell>
Thank you for any comments and/or suggestions!
Upvotes: 1
Views: 1840
Reputation: 8934
In order to use constructor injection with MAUI Shell, you need to register all required dependencies with the MauiAppBuilder
instance in your MauiProgram.cs file:
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
builder.Services.AddTransient<IVoterService>();
builder.Services.AddTransient<VotersListPageViewModel>();
builder.Services.AddTransient<VotersListPageView>();
You don't need to handle any of the dependency injection yourself like this, the constructor arguments are passed down by Shell automatically.
Note: You'll have to figure out yourself whether you need to register any of the classes as singletons or transients.
Gerald Verluis also wrote an answer to a similar problem here: https://stackoverflow.com/a/72433960/4308455.
James Montemagno has a great video about it on YouTube, as well: https://www.youtube.com/watch?v=xx1mve2AQr4.
Upvotes: 3