Manie Verster
Member
- Joined
- Nov 22, 2023
- Messages
- 22
- Programming Experience
- 10+
I recently started learning mobile app development in .NET Maui. I began with data-bound XAML pages. Then I wanted to create a menu in my app. After exploring some possibilities I decided on tab bar menus but I have a problem calling data-bound XAML pages. Here are the data classes I am using. This might be overkill but I wanted to rather give too much information than to little. Please can anyone help!
Create the SQLite database.
The Vehicle Master table.
The Vehicle Log table.
Vehicle Master XAML. From here I will only show the Vehicle Master files
Vehicle Master XAML cs file
AppShell XAML with tab bar menu
The error I am getting:
System.InvalidOperationException
Unable to resolve service for type 'VehicleLogs.VehicleLogDatabase' while attempting to activate 'VehicleLogs.Vehicles'.
Create the SQLite database.
Create the database:
using SQLite;
namespace VehicleLogs
{
public class VehicleLogDatabase
{
private const string db_name = "VehicleLogBook.db3";
private readonly SQLiteAsyncConnection _connection;
public VehicleLogDatabase()
{
_connection = new SQLiteAsyncConnection(Path.Combine(FileSystem.AppDataDirectory, db_name));
_connection.CreateTableAsync<VehicleMaster>();
_connection.CreateTableAsync<VehicleLog>();
}
public async Task<List<VehicleMaster>> GetVehicles()
{
return await _connection.Table<VehicleMaster>().ToListAsync();
}
public async Task<VehicleMaster> GetVehiclesById(int id)
{
return await _connection.Table<VehicleMaster>().Where(x => x.VehicleID == id).FirstOrDefaultAsync();
}
public async Task Create(VehicleMaster vehicleMaster)
{
await _connection.InsertAsync(vehicleMaster);
}
public async Task Update(VehicleMaster vehicleMaster)
{
await _connection.UpdateAsync(vehicleMaster);
}
public async Task Delete(VehicleMaster vehicleMaster)
{
await _connection.DeleteAsync(vehicleMaster);
}
public async Task<List<VehicleLog>> GetLogbook()
{
return await _connection.Table<VehicleLog>().ToListAsync();
}
public async Task<VehicleLog> GetLogbookById(int id)
{
return await _connection.Table<VehicleLog>().Where(x => x.LogID == id).FirstOrDefaultAsync();
}
public async Task Create(VehicleLog vehicleLogbook)
{
await _connection.InsertAsync(vehicleLogbook);
}
public async Task Update(VehicleLog vehicleLogbook)
{
await _connection.UpdateAsync(vehicleLogbook);
}
public async Task Delete(VehicleLog vehicleLogbook)
{
await _connection.DeleteAsync(vehicleLogbook);
}
}
}
The Vehicle Master table.
Vehicle Master table:
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VehicleLogs
{
[Table("VehicleMaster")]
public class VehicleMaster
{
[PrimaryKey]
[AutoIncrement]
[Column("VehicleID")]
public int VehicleID { get; set; }
[Column("RegNr")]
public string? RegNr { get; set; }
[Column("LastOdometer")]
public string? LastOdometer { get; set; }
}
}
The Vehicle Log table.
Vehicle Log table:
using SQLite;
namespace VehicleLogs
{
[Table("VehicleLog")]
public class VehicleLog
{
[PrimaryKey]
[AutoIncrement]
[Column("LogID")]
public int LogID { get; set; }
[PrimaryKey]
[Column("RegNr")]
public string? RegNr { get; set; }
[Column("StartOdometer")]
public string? StartOdometer { get; set; }
[Column("EndOdometer")]
public string? EndOdometer { get; set; }
}
}
Vehicle Master XAML. From here I will only show the Vehicle Master files
Vehicle Master 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"
x:Class="VehicleLogs.Vehicles"
Title="Vehicles">
<FlexLayout Direction="Column">
<VerticalStackLayout Padding="10" FlexLayout.Basis="400" BackgroundColor="Beige">
<Entry x:Name="regNrEntryField" Placeholder="Reg Number" />
<Entry x:Name="lastOdometerEntryField" Placeholder="Last Odometer" />
<Button x:Name="saveButton" Text="Save" Clicked="SaveButtonClicked"/>
</VerticalStackLayout>
<ListView x:Name="ListView" HasUnevenRows="True" ItemTapped="ListView_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<VerticalStackLayout Padding="5">
<Label Text="(Binding RegNr)" FontSize="17" FontAttributes="Bold" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text="={Binding RegNr}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="={Binding LastOdometer}" FontAttributes="Bold" />
</Grid>
</VerticalStackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</FlexLayout>
</ContentPage>
Vehicle Master XAML cs file
Vehicle Master XAML cs file:
namespace VehicleLogs;
public partial class Vehicles : ContentPage
{
private readonly VehicleLogDatabase _dbService;
private int _editVehicleID;
public Vehicles(VehicleLogDatabase dbService)
{
InitializeComponent();
_dbService = dbService;
Task.Run(async () => ListView.ItemsSource = await _dbService.GetVehicles());
}
private async void SaveButtonClicked(object sender, EventArgs e)
{
if (_editVehicleID == 0)
{
await _dbService.Create(new VehicleMaster
{
RegNr = regNrEntryField.Text,
LastOdometer = lastOdometerEntryField.Text
});
}
else
{
await _dbService.Update(new VehicleMaster
{
VehicleID = _editVehicleID,
RegNr = regNrEntryField.Text,
LastOdometer = lastOdometerEntryField.Text
});
_editVehicleID = 0;
}
regNrEntryField.Text = string.Empty;
lastOdometerEntryField.Text = string.Empty;
ListView.ItemsSource = await _dbService.GetVehicles();
}
private async void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var vehicleMaster = (VehicleMaster)e.Item;
var action = await DisplayActionSheet("Action", "Cancel", "Edit", "Delete");
switch (action)
{
case "Edit":
_editVehicleID = vehicleMaster.VehicleID;
regNrEntryField.Text = vehicleMaster.RegNr;
lastOdometerEntryField.Text = vehicleMaster.LastOdometer;
break;
case "Delete":
await _dbService.Delete(vehicleMaster);
ListView.ItemsSource = await _dbService.GetVehicles();
break;
}
}
}
AppShell XAML with tab bar menu
AppShell XAML:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="VehicleLogs.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:VehicleLogs"
Shell.FlyoutBehavior="Disabled"
Title="VehicleLogs">
<TabBar>
<Tab Title="Home">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage"/>
</Tab>
<Tab Title="Vehicles">
<ShellContent
Title="Vehicles"
ContentTemplate="{DataTemplate local:Vehicle}"
Route="Vehicle"/>
</Tab>
<Tab Title="Log Mileage">
<ShellContent
Title="Log Mileage"
ContentTemplate="{DataTemplate local:LogVehicle}"
Route="LogVehicle"/>
</Tab>
</TabBar>
</Shell>