Skip to content

Commit

Permalink
#3785 Update to MAUI sample for CSLA 9. This also fixes several desig…
Browse files Browse the repository at this point in the history
…n issues for how a MAUI application should use dependency injection and navigation. The service locator has been removed. Fixing the issue with the navigation also fixed the issue with how dependency injection should be done. (#4418)
  • Loading branch information
Bowman74 authored Dec 30, 2024
1 parent 6905ebc commit e4e8ab6
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 60 deletions.
6 changes: 3 additions & 3 deletions Samples/MauiExample/BusinessLibrary/BusinessLibrary.csproj
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Csla" Version="8.0.0-R24021202" />
<PackageReference Include="Csla" Version="9.0.0-rc1-gb7b53fbc46" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Samples/MauiExample/DataAccess/DataAccess.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

Expand Down
17 changes: 13 additions & 4 deletions Samples/MauiExample/MauiExample/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Csla;
using MauiExample.Pages;

namespace MauiExample;

Expand All @@ -7,9 +7,18 @@ public partial class App : Application
public App()
{
InitializeComponent();
RegisterRoutes();

MainPage = new AppShell();
}
}

public static ApplicationContext ApplicationContext { get; set; }
public void RegisterRoutes()
{
Routing.RegisterRoute(Constants.PersonEditRoute, typeof(PersonEditPage));
Routing.RegisterRoute(Constants.PersonListRoute, typeof(PersonListPage));
}

protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new AppShell());
}
}
14 changes: 14 additions & 0 deletions Samples/MauiExample/MauiExample/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MauiExample;
internal static class Constants
{
public const string PersonEditRoute = "PersonEditRoute";
public const string PersonListRoute = "PersonListRoute";

public const string PersonIdParameter = "PersonId";
}
47 changes: 31 additions & 16 deletions Samples/MauiExample/MauiExample/MauiExample.csproj
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType>
<RootNamespace>MauiExample</RootNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>

<Nullable>enable</Nullable>
<MauiEnableXamlCBindingWithSourceCompilation>true</MauiEnableXamlCBindingWithSourceCompilation>

<!-- Display name -->
<ApplicationTitle>MauiExample</ApplicationTitle>

Expand All @@ -22,43 +24,55 @@
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>

<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-android|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-ios|AnyCPU'">
<CodesignResourceRules></CodesignResourceRules>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-ios|AnyCPU'">
<CodesignResourceRules></CodesignResourceRules>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)'=='net9.0-ios'">
<ProvisioningType>automatic</ProvisioningType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-android|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-android|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-android|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-ios|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-ios|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-ios|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-ios|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-maccatalyst|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-maccatalyst|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-maccatalyst|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-maccatalyst|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows10.0.19041.0|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net9.0-windows10.0.19041.0|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows10.0.19041.0|AnyCPU'">
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0-windows10.0.19041.0|AnyCPU'">
<DefineConstants>$(DefineConstants)TRACE;MAUI</DefineConstants>
</PropertyGroup>

Expand All @@ -84,8 +98,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Csla.Maui" Version="8.0.0-R24021202" />
</ItemGroup>
<PackageReference Include="Csla.Maui" Version="9.0.0-rc1-gb7b53fbc46" />
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.21" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\BusinessLibrary\BusinessLibrary.csproj" />
Expand All @@ -100,5 +116,4 @@
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
</ItemGroup>

</Project>
16 changes: 11 additions & 5 deletions Samples/MauiExample/MauiExample/MauiProgram.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Csla;
using Csla.Configuration;
using Csla.Configuration;
using MauiExample.ViewModels;

namespace MauiExample;

Expand All @@ -16,13 +16,19 @@ public static MauiApp CreateMauiApp()
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});

builder.Services.AddTransient<DataAccess.IPersonDal, DataAccess.PersonDal>();
builder.Services.AddCsla(options => options
.AddXaml());

var provider = builder.Services.BuildServiceProvider();
App.ApplicationContext = provider.GetRequiredService<ApplicationContext>();
AddDependancyInjection(builder);

return builder.Build();
}

private static void AddDependancyInjection(MauiAppBuilder builder)
{
builder.Services.AddTransient<DataAccess.IPersonDal, DataAccess.PersonDal>();

builder.Services.AddScoped<PersonEditViewModel>();
builder.Services.AddScoped<PersonListViewModel>();
}
}
14 changes: 8 additions & 6 deletions Samples/MauiExample/MauiExample/Pages/PersonEditPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:csla="clr-namespace:Csla.Xaml;assembly=Csla.Xaml"
xmlns:vms="clr-namespace:MauiExample.ViewModels"
xmlns:models="clr-namespace:BusinessLibrary;assembly=BusinessLibrary"
x:Class="MauiExample.Pages.PersonEditPage"
Title="Person Edit">
<VerticalStackLayout>
Expand All @@ -13,7 +15,7 @@
Margin="10,0,0,10"
SemanticProperties.HeadingLevel="Level1"/>
</HorizontalStackLayout>
<Grid BindingContext="{Binding Model}">
<Grid BindingContext="{Binding Model, x:DataType=vms:PersonEditViewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="Auto" />
Expand All @@ -25,14 +27,14 @@
</Grid.ColumnDefinitions>
<Label Text="Name" Grid.Row="1" Grid.Column="0" />
<HorizontalStackLayout Grid.Row="1" Grid.Column="1">
<Entry Text="{Binding Name}" WidthRequest="200" />
<Entry Text="{Binding Name, x:DataType=models:PersonEdit}" WidthRequest="200" />
<csla:PropertyInfo Path="Name" x:Name="NameInfo" />
<Label TextColor="Red" BindingContext="{x:Reference NameInfo}" Text="{Binding ErrorText}" Margin="3" />
<Label TextColor="Yellow" BindingContext="{x:Reference NameInfo}" Text="{Binding WarningText}" Margin="3" />
<Label TextColor="LightGreen" BindingContext="{x:Reference NameInfo}" Text="{Binding InformationText}" Margin="3" />
<Label TextColor="Red" BindingContext="{x:Reference NameInfo}" Text="{Binding ErrorText, x:DataType=csla:PropertyInfo}" Margin="3" />
<Label TextColor="Yellow" BindingContext="{x:Reference NameInfo}" Text="{Binding WarningText, x:DataType=csla:PropertyInfo}" Margin="3" />
<Label TextColor="LightGreen" BindingContext="{x:Reference NameInfo}" Text="{Binding InformationText, x:DataType=csla:PropertyInfo}" Margin="3" />
</HorizontalStackLayout>
<HorizontalStackLayout Grid.Row="2" Grid.Column="1" >
<Button Text="Save" IsEnabled="{Binding IsSavable}" Clicked="SavePerson" Margin="3" />
<Button Text="Save" IsEnabled="{Binding IsSavable, x:DataType=models:PersonEdit}" Clicked="SavePerson" Margin="3" />
<Button Text="Close" Clicked="ClosePage" Margin="3" />
</HorizontalStackLayout>
</Grid>
Expand Down
33 changes: 20 additions & 13 deletions Samples/MauiExample/MauiExample/Pages/PersonEditPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@

namespace MauiExample.Pages;

public partial class PersonEditPage : ContentPage
public partial class PersonEditPage : ContentPage, IQueryAttributable
{
public PersonEditPage()
private IDataPortal<PersonEdit> _personDataPortal;

public PersonEditPage(PersonEditViewModel viewModel, IDataPortal<PersonEdit> dataPortal)
{
BindingContext = new PersonEditViewModel();
InitializeComponent();
}

public PersonEditPage(int personId)
:this()
{
_personId = personId;
BindingContext = viewModel;
_personDataPortal = dataPortal;
}

private bool _isLoaded;
Expand All @@ -33,22 +31,31 @@ protected override async void OnAppearing()
private async Task RefreshData(int id)
{
var vm = (PersonEditViewModel)BindingContext;
var dp = App.ApplicationContext.GetRequiredService<IDataPortal<PersonEdit>>();
if (id < 1)
await vm.RefreshAsync<PersonEdit>(async () => await dp.CreateAsync());
await vm.RefreshAsync<PersonEdit>(async () => await _personDataPortal.CreateAsync());
else
await vm.RefreshAsync<PersonEdit>(async () => await dp.FetchAsync(id));
await vm.RefreshAsync<PersonEdit>(async () => await _personDataPortal.FetchAsync(id));
}

private async void SavePerson(object sender, EventArgs e)
{
var vm = (PersonEditViewModel)BindingContext;
await vm.SaveAsync();
await Navigation.PopModalAsync();
await Shell.Current.GoToAsync("..", true);
}

private async void ClosePage(object sender, EventArgs e)
{
await Navigation.PopModalAsync();
await Shell.Current.GoToAsync("..", true);
}

public void ApplyQueryAttributes(IDictionary<string, object> query)
{
if (query != null && query.ContainsKey(Constants.PersonIdParameter))
{
int? personId = query[Constants.PersonIdParameter] as int?;
if (personId.HasValue)
_personId = personId.Value;
}
}
}
7 changes: 4 additions & 3 deletions Samples/MauiExample/MauiExample/Pages/PersonListPage.xaml
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
<?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:vms="clr-namespace:MauiExample.ViewModels"
xmlns:models="clr-namespace:BusinessLibrary;assembly=BusinessLibrary"
x:Class="MauiExample.Pages.PersonListPage"
Title="Person List">

<Grid>
<ListView ItemsSource="{Binding Model}">
<ListView ItemsSource="{Binding Model, x:DataType=vms:PersonListViewModel}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name}" WidthRequest="100" Margin="5" TextColor="Black" />
<Label Text="{Binding Name, x:DataType=models:PersonInfo}" WidthRequest="100" Margin="5" TextColor="Black" />
<Button Text="Edit" Clicked="EditPerson" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>

</ContentPage>
23 changes: 15 additions & 8 deletions Samples/MauiExample/MauiExample/Pages/PersonListPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ namespace MauiExample.Pages;

public partial class PersonListPage : ContentPage
{
public PersonListPage()

private IDataPortal<PersonList> _PersonListDataPortal;

public PersonListPage(PersonListViewModel viewModel, IDataPortal<PersonList> dataPortal)
{
InitializeComponent();

this.BindingContext = new PersonListViewModel();
_PersonListDataPortal = dataPortal;
this.BindingContext = viewModel;
}

protected override async void OnAppearing()
Expand All @@ -25,14 +29,17 @@ protected override async void OnAppearing()
private async Task RefreshData()
{
var vm = (PersonListViewModel)BindingContext;
var dp = App.ApplicationContext.GetRequiredService<IDataPortal<PersonList>>();
await vm.RefreshAsync<PersonList>(async () => await dp.FetchAsync());
await vm.RefreshAsync<PersonList>(async () => await _PersonListDataPortal.FetchAsync());
}

private void EditPerson(object sender, EventArgs e)
private async void EditPerson(object sender, EventArgs e)
{
var btn = sender as Button;
var data = btn.BindingContext as PersonInfo;
Navigation.PushModalAsync(new PersonEditPage(data.Id));
var btn = (Button)sender;
var data = (PersonInfo)btn.BindingContext;

var pageParams = new ShellNavigationQueryParameters();

pageParams.Add(Constants.PersonIdParameter, data.Id);
await Shell.Current.GoToAsync(Constants.PersonEditRoute, true, pageParams);
}
}

0 comments on commit e4e8ab6

Please sign in to comment.