Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General Updates #17

Merged
merged 11 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
<PackageProjectUrl>https://github.com/AvantiPoint/mauimicromvvm</PackageProjectUrl>
<NeutralLanguage>en</NeutralLanguage>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<NoWarn>$(NoWarn);NU1507</NoWarn>
<IsPackable>$(MSBuildProjectName.Contains('MauiMicroMvvm'))</IsPackable>
</PropertyGroup>

<PropertyGroup>
Expand Down
5 changes: 5 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<Project>
<PropertyGroup>
<PackageId>AvantiPoint.$(AssemblyName)</PackageId>
</PropertyGroup>
</Project>
2 changes: 2 additions & 0 deletions MauiMicroMvvm.sln
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{58DDD03C-E4B7-431A-8BC4-B8A8199C3DCD}"
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
Directory.Packages.props = Directory.Packages.props
EndProjectSection
EndProject
Global
Expand Down
13 changes: 13 additions & 0 deletions sample/MauiMicroSample/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiMicroSample.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
9 changes: 9 additions & 0 deletions sample/MauiMicroSample/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace MauiMicroSample;

public partial class App : Application
{
public App()
{
InitializeComponent();
}
}
5 changes: 2 additions & 3 deletions sample/MauiMicroSample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiMicroMvvm<AppShell>(
"Resources/Styles/Colors.xaml",
"Resources/Styles/Styles.xaml")
.UseMauiApp<App>()
.UseMauiMicroMvvm<AppShell>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
Expand Down
3 changes: 0 additions & 3 deletions src/MauiMicroMvvm.Rx/MauiMicroMvvm.Rx.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@

<PropertyGroup>
<TargetFramework>$(DotNetVersion)</TargetFramework>
<UseMaui>true</UseMaui>
<ImplicitUsings>enable</ImplicitUsings>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Description>MauiMicroMvvm.Rx is the perfect companion for people who love Reactive design &amp; want to couple it with MauiMicro. With MauiMicro Rx you get an Observables first base ViewModel that let's you design your code around an observable for the App &amp; View lifecycles.</Description>
<PackageTags>dotnet-maui;mvvm;mauimicro;reactive;rx</PackageTags>
<PackageId>AvantiPoint.$(AssemblyName)</PackageId>
<Title>$(AssemblyName)</Title>
</PropertyGroup>

Expand Down
4 changes: 2 additions & 2 deletions src/MauiMicroMvvm.Rx/RxMauiMicroViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class RxMauiMicroViewModel : ReactiveObject, IViewModelActivation, IViewL
private readonly Subject<ViewLifecycleState> _viewLifecycleState;
private readonly Subject<IDictionary<string, object>> _queryParameters;
private readonly Lazy<ILogger> _lazyLogger;
protected ObservableAsPropertyHelper<bool> IsBusyHelper;
protected ObservableAsPropertyHelper<bool>? IsBusyHelper;
private readonly ObservableAsPropertyHelper<bool> _isNotBusyHelper;
protected readonly CompositeDisposable Disposables;

Expand All @@ -21,7 +21,7 @@ public RxMauiMicroViewModel(ViewModelContext context)
_applifecycleState = new Subject<AppLifecycleState>();
_viewLifecycleState = new Subject<ViewLifecycleState>();
_queryParameters = new Subject<IDictionary<string, object>>();
Disposables = new CompositeDisposable();
Disposables = [];
Navigation = context.Navigation;
PageDialogs = context.PageDialogs;
_lazyLogger = new Lazy<ILogger>(() => context.Logger.CreateLogger(GetType().Name));
Expand Down
2 changes: 1 addition & 1 deletion src/MauiMicroMvvm.Templates/MauiMicroMvvm.Templates.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
<IncludeSymbols>false</IncludeSymbols>
<IncludeSource>false</IncludeSource>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
<Description>Project Template for Maui Micro by AvantiPoint</Description>
<PackageTags>dotnet-maui;mauimicro;mauimicromvvm;mauimicrotemplates;templates;mvvm;maui;</PackageTags>
<PackageId>AvantiPoint.$(AssemblyName)</PackageId>
<Title>MauiMicroMvvm Templates</Title>
<NoWarn>$(NoWarn);NU5128</NoWarn>
</PropertyGroup>
Expand Down
13 changes: 13 additions & 0 deletions src/MauiMicroMvvm.Templates/content/MauiMicroApp.1/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiMicroApp._1.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace MauiMicroApp._1;

public partial class App : Application
{
public App()
{
InitializeComponent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiMicroMvvm<AppShell>(
"Resources/Styles/Colors.xaml",
"Resources/Styles/Styles.xaml")
.UseMauiApp<App>()
.UseMauiMicroMvvm<AppShell>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
Expand Down
27 changes: 27 additions & 0 deletions src/MauiMicroMvvm/Behaviors/BehaviorFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace MauiMicroMvvm.Behaviors;

public sealed class BehaviorFactory : IBehaviorFactory
{
private readonly IEnumerable<IRegisteredBehavior> _behaviors;
private readonly IServiceProvider _services;

public BehaviorFactory(IServiceProvider services, IEnumerable<IRegisteredBehavior> behaviors)
{
ArgumentNullException.ThrowIfNull(services);
_behaviors = behaviors ?? [];
_services = services;
}

public void ApplyBehaviors(VisualElement element)
{
foreach (var registration in _behaviors)
{
if (!registration.ViewType.IsAssignableFrom(registration.ViewType))
continue;

var behavior = registration.GetBehavior();
if (behavior is not null)
element.Behaviors.Add(behavior);
}
}
}
24 changes: 24 additions & 0 deletions src/MauiMicroMvvm/Behaviors/DelegateViewBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
namespace MauiMicroMvvm.Behaviors;

internal sealed class DelegateViewBehavior<TView>(Action<IServiceProvider, TView> onAttached, Action<IServiceProvider, TView> onDetached) : Behavior<TView>
where TView : VisualElement
{
private readonly Action<IServiceProvider, TView> _onAttached = onAttached;
private readonly Action<IServiceProvider, TView> _onDetached = onDetached;

protected override void OnAttachedTo(TView bindable)
{
base.OnAttachedTo(bindable);
var serviceProvider = bindable.Handler?.MauiContext?.Services;
ArgumentNullException.ThrowIfNull(serviceProvider);
_onAttached(serviceProvider, bindable);
}

protected override void OnDetachingFrom(TView bindable)
{
base.OnDetachingFrom(bindable);
var serviceProvider = bindable.Handler?.MauiContext?.Services;
ArgumentNullException.ThrowIfNull(serviceProvider);
_onDetached(serviceProvider, bindable);
}
}
6 changes: 6 additions & 0 deletions src/MauiMicroMvvm/Behaviors/IBehaviorFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace MauiMicroMvvm.Behaviors;

public interface IBehaviorFactory
{
void ApplyBehaviors(VisualElement element);
}
7 changes: 7 additions & 0 deletions src/MauiMicroMvvm/Behaviors/IRegisteredBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace MauiMicroMvvm.Behaviors;

public interface IRegisteredBehavior
{
Type ViewType { get; }
Behavior GetBehavior();
}
10 changes: 10 additions & 0 deletions src/MauiMicroMvvm/Behaviors/RegisteredBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace MauiMicroMvvm.Behaviors;

internal class RegisteredBehavior<TView, TBehavior>(IServiceProvider Services) : IRegisteredBehavior
where TView : VisualElement
where TBehavior : Behavior
{
public Type ViewType => typeof(TView);

public Behavior GetBehavior() => Services.GetRequiredService<TBehavior>();
}
42 changes: 42 additions & 0 deletions src/MauiMicroMvvm/Common/MvvmHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Microsoft.Maui.Controls;

namespace MauiMicroMvvm.Common;

public static class MvvmHelpers
{
public static void InvokeViewViewModelAction<T>(object? value, Action<T> action)
{
if (value is T valueAsT)
{
action(valueAsT);
}

if (value is BindableObject bindable)
{
InvokeViewViewModelAction(bindable.BindingContext, action);
}
}

public static async Task InvokeViewViewModelActionAsync<T>(object? value, Func<T, Task> action)
{
if (value is T valueAsT)
{
await action(valueAsT);
}

if (value is BindableObject bindable)
{
await InvokeViewViewModelActionAsync(bindable.BindingContext, action);
}
}

public static void Destroy(object? page)
{
InvokeViewViewModelAction<IDisposable>(page, x => x.Dispose());
}

public static Task DestroyAsync(object? page)
{
return InvokeViewViewModelActionAsync<IAsyncDisposable>(page, x => x.DisposeAsync().AsTask());
}
}
62 changes: 42 additions & 20 deletions src/MauiMicroMvvm/Internals/AppLifecycleBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.ComponentModel;
using MauiMicroMvvm.Common;
using MauiMicroMvvm.Xaml;

namespace MauiMicroMvvm.Internals;
Expand All @@ -8,13 +9,15 @@ public class AppLifecycleBehavior : Behavior
{
private bool _didAppear;
private bool _isVisible;
private Window _window;
public Page Page { get; set; }
private Window? _window;
public Page? Page { get; set; }

public BindableObject View { get; set; }
public BindableObject? View { get; set; }

protected override void OnAttachedTo(BindableObject bindable)
{
ArgumentNullException.ThrowIfNull(Page);
ArgumentNullException.ThrowIfNull(View);
base.OnAttachedTo(bindable);
Page.Appearing += OnAppearing;
Page.Disappearing += OnDisappearing;
Expand All @@ -34,13 +37,19 @@ protected override void OnAttachedTo(BindableObject bindable)
}
}

protected override void OnDetachingFrom(BindableObject bindable)
protected override async void OnDetachingFrom(BindableObject bindable)
{
ArgumentNullException.ThrowIfNull(Page);
ArgumentNullException.ThrowIfNull(View);

base.OnDetachingFrom(bindable);
Page.Appearing -= OnAppearing;
Page.Disappearing -= OnDisappearing;
Page.PropertyChanged -= OnPagePropertyChanged;
View.PropertyChanged -= OnViewPropertyChanged;

MvvmHelpers.Destroy(View);
await MvvmHelpers.DestroyAsync(View);
if (_window is not null)
{
_window.Resumed -= OnResumed;
Expand All @@ -50,8 +59,11 @@ protected override void OnDetachingFrom(BindableObject bindable)
Page = null;
}

private void OnViewPropertyChanged(object sender, PropertyChangedEventArgs e)
private void OnViewPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
ArgumentNullException.ThrowIfNull(Page);
ArgumentNullException.ThrowIfNull(View);

if (e.PropertyName != MauiMicro.SharedContextProperty.PropertyName)
return;

Expand All @@ -60,8 +72,11 @@ private void OnViewPropertyChanged(object sender, PropertyChangedEventArgs e)
MauiMicro.SetSharedContext(Page, value);
}

private void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
private void OnPagePropertyChanged(object? sender, PropertyChangedEventArgs e)
{
ArgumentNullException.ThrowIfNull(Page);
ArgumentNullException.ThrowIfNull(View);

if (e.PropertyName != MauiMicro.SharedContextProperty.PropertyName)
return;

Expand All @@ -70,32 +85,39 @@ private void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
MauiMicro.SetSharedContext(View, value);
}

private void OnResumed(object sender, EventArgs e)
private void OnResumed(object? sender, EventArgs e)
{
if (_isVisible && View.BindingContext is IAppLifecycle lifecycle)
lifecycle.OnResume();
MvvmHelpers.InvokeViewViewModelAction<IAppLifecycle>(View, x => x.OnResume());
}

private void OnStopped(object sender, EventArgs e)
private void OnStopped(object? sender, EventArgs e)
{
if (_isVisible && View.BindingContext is IAppLifecycle lifecycle)
lifecycle.OnSleep();
MvvmHelpers.InvokeViewViewModelAction<IAppLifecycle>(View, x => x.OnSleep());
}

private void OnAppearing(object sender, EventArgs e)
private void OnAppearing(object? sender, EventArgs e)
{
if (!_didAppear && View.BindingContext is IViewModelActivation initialize)
initialize.OnFirstLoad();
if (!_didAppear)
{
MvvmHelpers.InvokeViewViewModelAction<IViewModelActivation>(View, x => x.OnFirstLoad());
}

_didAppear = true;
if (View.BindingContext is IViewLifecycle lifecycle)
lifecycle.OnAppearing();

if (!_isVisible)
{
MvvmHelpers.InvokeViewViewModelAction<IViewLifecycle>(View, x => x.OnAppearing());
}

_isVisible = true;
}

private void OnDisappearing(object sender, EventArgs e)
private void OnDisappearing(object? sender, EventArgs e)
{
if (View.BindingContext is IViewLifecycle lifecycle)
lifecycle.OnDisappearing();
if (_isVisible)
{
MvvmHelpers.InvokeViewViewModelAction<IViewLifecycle>(View, x => x.OnDisappearing());
}

_isVisible = false;
}
Expand Down
Loading
Loading