Skip to content

Commit

Permalink
We now have some tabs & nav stacks picking up properly
Browse files Browse the repository at this point in the history
  • Loading branch information
aritchie committed May 31, 2024
1 parent 287b1d4 commit 56a9d5b
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 32 deletions.
13 changes: 13 additions & 0 deletions Sample/AnotherPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?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:sample="clr-namespace:Sample"
x:DataType="sample:AnotherViewModel"
x:Class="Sample.AnotherPage"
Title="Another Page">
<ContentPage.Content>
<Label Text="This Page will now participate in the event handler chain as long as it stays in this navigation stack"
HorizontalTextAlignment="Center"
HorizontalOptions="Fill" />
</ContentPage.Content>
</ContentPage>
15 changes: 15 additions & 0 deletions Sample/AnotherPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sample;

public partial class AnotherPage : ContentPage
{
public AnotherPage()
{
InitializeComponent();
}
}
8 changes: 8 additions & 0 deletions Sample/AnotherViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Sample;


public class AnotherViewModel(BaseServices services, AppSqliteConnection conn) : ViewModel(services), IEventHandler<MyMessageEvent>
{
public Task Handle(MyMessageEvent @event, CancellationToken cancellationToken) =>
conn.Log("AnotherViewModel", @event);
}
8 changes: 8 additions & 0 deletions Sample/BlazorPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Sample.Components"
xmlns:sample="clr-namespace:Sample"
x:DataType="sample:BlazorViewModel"
x:Class="Sample.BlazorPage"
Title="Blazor">

<ContentPage.ToolbarItems>
<ToolbarItem Text="Another Page"
Command="{Binding Navigate}"
CommandParameter="AnotherPage" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<BlazorWebView x:Name="blazorWebView"
HostPage="wwwroot/index.html">
Expand Down
5 changes: 1 addition & 4 deletions Sample/BlazorViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
namespace Sample;

public class BlazorViewModel : ViewModel
public class BlazorViewModel(BaseServices services) : ViewModel(services)
{
public BlazorViewModel(BaseServices services) : base(services)
{
}
}
5 changes: 1 addition & 4 deletions Sample/EventViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


namespace Sample;


Expand All @@ -19,7 +17,7 @@ AppSqliteConnection conn
x.Arg,
x.FireAndForget,
x.ParallelEvents,
x.Timestamp.ToString("g")
x.Timestamp.ToLocalTime().ToString("g")
))
.ToList();
});
Expand All @@ -40,7 +38,6 @@ AppSqliteConnection conn
public ICommand Load { get; }
[Reactive] public List<EventItemViewModel> List { get; private set; }


public override void OnAppearing()
{
base.OnAppearing();
Expand Down
1 change: 1 addition & 0 deletions Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static MauiApp CreateMauiApp()
builder.Services.RegisterForNavigation<TriggerPage, TriggerViewModel>();
builder.Services.RegisterForNavigation<EventPage, EventViewModel>();
builder.Services.RegisterForNavigation<BlazorPage, BlazorViewModel>();
builder.Services.RegisterForNavigation<AnotherPage, AnotherViewModel>();

return builder.Build();
}
Expand Down
1 change: 1 addition & 0 deletions Sample/Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\src\Shiny.Mediator.Contracts\Shiny.Mediator.Contracts.csproj" />
<ProjectReference Include="..\src\Shiny.Mediator.Maui\Shiny.Mediator.Maui.csproj" />
<ProjectReference Include="..\src\Shiny.Mediator\Shiny.Mediator.csproj" />
</ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and dependency injection can't reach.
* Fire & Forget as well as Parallel Event execution
* Our MAUI & Blazor integrations allow your viewmodels or pages to implement an IEventHandler<TEvent> interface(s) without them having to participate in the dependency injection provider
* We still have a "messagingcenter" type subscribe off IMediator for cases where you can't have your current type implement an interface
* Instead of Assembly Scanning, we have source generators to automatically wireup the necessary registrations for you!
* Lightweight, No external dependencies, tiny bit of reflection
* Help remove service overrun and reduce your constructor fat
* Easy to Unit Test

## Works With
* .NET MAUI - all platforms
Expand Down Expand Up @@ -159,6 +163,6 @@ Focus on the interfaces from the mediator & the mediator calls itself
* Pipelines
* Error handlers - requests and events?
* Pre/Post Execution - Time how long events took, time how long a command took

* Explain Event Handlers
* Streams - IAsyncEnumerable or IObservable
* Source Generator Registration
67 changes: 47 additions & 20 deletions src/Shiny.Mediator.Maui/MauiEventCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,58 @@ public class MauiEventCollector : IEventCollector
{
public IReadOnlyList<IEventHandler<TEvent>> GetHandlers<TEvent>() where TEvent : IEvent
{
// I need to make this crawl the tree, but really I don't need a ton of use-cases here
var list = new List<IEventHandler<TEvent>>();
var proxy = Application.Current?.NavigationProxy;
if (proxy != null)
var mainPage = Application.Current?.MainPage;
if (mainPage == null)
return list;

if (mainPage is TabbedPage tabs)
{
foreach (var page in proxy.NavigationStack)
foreach (var tab in tabs.Children)
{
// if (page is TabbedPage tabs)
// {
// foreach (var tab in tabs.Children)
// {
// tab.NavigationProxy
// }
// }
// if (page is NavigationPage nav)
// {
// nav.NavigationProxy
// }

if (page is IEventHandler<TEvent> handler1)
list.Add(handler1);

if (page.BindingContext is IEventHandler<TEvent> handler2)
list.Add(handler2);
if (tab is NavigationPage navPage)
{
TryAppendEvents(navPage, list);
}
else
{
TryAppendEvents(tab, list);
}
}
}
else if (mainPage is NavigationPage navPage)
{
TryAppendEvents(navPage, list);
}
else
{
TryAppendEvents(mainPage!, list);
}

return list;
}


static void TryAppendEvents<TEvent>(Page page, List<IEventHandler<TEvent>> list) where TEvent : IEvent
{
if (page is IEventHandler<TEvent> handler1)
list.Add(handler1);

if (page.BindingContext is IEventHandler<TEvent> handler2)
list.Add(handler2);
}


static void TryAppendEvents<TEvent>(NavigationPage navPage, List<IEventHandler<TEvent>> list) where TEvent : IEvent
{
var navStack = navPage.Navigation?.NavigationStack;
if (navStack != null)
{
foreach (var page in navStack)
{
TryAppendEvents(page, list);
}
}
}
}
16 changes: 13 additions & 3 deletions src/Shiny.Mediator/Impl/Mediator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public async Task Send<TRequest>(TRequest request, CancellationToken cancellatio
AssertRequestHandlers(handlers.Count, request);

// TODO: pipelines
await handlers.First().Handle(request, cancellationToken).ConfigureAwait(false);
await handlers
.First()
.Handle(request, cancellationToken)
.ConfigureAwait(false);
}


Expand All @@ -46,11 +49,12 @@ public async Task Publish<TEvent>(
CancellationToken cancellationToken = default
) where TEvent : IEvent
{
// TODO: filter out the dupes from the collector by instance (viewmodels may be in DI and MAUI collector)
var handlers = services.GetServices<IEventHandler<TEvent>>().ToList();
AppendHandlersIf(handlers, this.subscriptions);
if (collector != null)
AppendHandlersIf(handlers, collector);

if (handlers.Count == 0)
return;

Expand Down Expand Up @@ -114,7 +118,13 @@ static void AppendHandlersIf<TEvent>(List<IEventHandler<TEvent>> list, IEventCol
{
var handlers = collector.GetHandlers<TEvent>();
if (handlers.Count > 0)
list.AddRange(handlers);
{
foreach (var handler in handlers)
{
if (!list.Contains(handler))
list.Add(handler);
}
}
}


Expand Down

0 comments on commit 56a9d5b

Please sign in to comment.