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

Use AspNetCore Router for URI navigation #117

Merged
merged 2 commits into from
Mar 31, 2023
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
2 changes: 1 addition & 1 deletion samples/ControlGallery/AppShell.razor
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
@*Navigation*@
<ShellSection Title="Navigation">
<NavigationPage />
<ShellNavigationPage />
<UriNavigationPage />
</ShellSection>

@*Other*@
Expand Down
43 changes: 0 additions & 43 deletions samples/ControlGallery/Views/Navigation/ShellNavigationPage.razor

This file was deleted.

This file was deleted.

45 changes: 45 additions & 0 deletions samples/ControlGallery/Views/Navigation/UriNavigationPage.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
@page "/shell-navigation"
@using ControlGallery.Models
@inject Navigation NavigationManager

<ContentPage Title="URI navigation">
<ScrollView>
<StackLayout>
<Button Text="Navigate with no parameters" OnClick="NavigateNoParameter"></Button>
<Button Text="Navigate with name string" OnClick="NavigateWithName"></Button>
<Button Text="Navigate with name string (with subpath)" OnClick="NavigateWithNameSubpath"></Button>
<Button Text="Navigate with name string and version int" OnClick="NavigateWithNameAndVersion"></Button>
<Button Text="Navigate with name, version, date" OnClick="NavigateWithNameVersionDate"></Button>
<Button Text="Navigate with Long" OnClick="NavigateWithLong"></Button>
<Button Text="Navigate with double" OnClick="NavigateWithDouble"></Button>
<Button Text="Navigate with float" OnClick="NavigateWithFloat"></Button>
<Button Text="Navigate with decimal" OnClick="NavigateWithDecimal"></Button>
<Button Text="Navigate with Guid" OnClick="NavigateWithGuid"></Button>
<Button Text="Navigate with Nullable<Guid>" OnClick="NavigateWithNullableGuid"></Button>
<Button Text="Navigate with Bool" OnClick="NavigateWithBool"></Button>
<Button Text="Navigate with query parameters" OnClick="NavigateWithAdditionalParameters"></Button>
</StackLayout>
</ScrollView>
</ContentPage>

@code
{
async Task NavigateNoParameter() => await NavigationManager.NavigateToAsync("/target");
async Task NavigateWithName() => await NavigationManager.NavigateToAsync("/target/maui");
async Task NavigateWithNameSubpath() => await NavigationManager.NavigateToAsync("/target/maui/subpath");
async Task NavigateWithNameAndVersion() => await NavigationManager.NavigateToAsync("/target/maui/5");
async Task NavigateWithNameVersionDate() => await NavigationManager.NavigateToAsync("/target/maui/5/2020-09-12");
async Task NavigateWithLong() => await NavigationManager.NavigateToAsync("/long/55");
async Task NavigateWithDouble() => await NavigationManager.NavigateToAsync("/double/55.43");
async Task NavigateWithFloat() => await NavigationManager.NavigateToAsync("/float/55.43");
async Task NavigateWithDecimal() => await NavigationManager.NavigateToAsync("/decimal/55.43");
async Task NavigateWithGuid() => await NavigationManager.NavigateToAsync($"/guid/{Guid.NewGuid()}");
async Task NavigateWithNullableGuid() => await NavigationManager.NavigateToAsync($"/nullable-guid/{Guid.NewGuid()}");
async Task NavigateWithBool() => await NavigationManager.NavigateToAsync("/bool/true");

async Task NavigateWithAdditionalParameters() => await NavigationManager.NavigateToAsync("/target", new Dictionary<string, object>
{
["Query1"] = new NavigationParameterModel("Q1", "V1"),
["Query2"] = new NavigationParameterModel("Q2", null)
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
@page "/target"
@page "/target/{Name}"
@page "/target/{Name}/subpath"
@page "/target/{Name}/{Version:int}"
@page "/target/{Name}/{Version:int}/{ReleaseDate:datetime}"
@page "/long/{Long:long}"
@page "/double/{Double:double}"
@page "/float/{Float:float}"
@page "/decimal/{Decimal:decimal}"
@page "/guid/{Guid:guid}"
@page "/nullable-guid/{NullableGuid:guid?}"
@page "/bool/{Bool:bool}"
@using ControlGallery.Models

<ContentPage>
<StackLayout>
<Label Text="Successfully navigated using Uri navigation"></Label>
@if (Name != null)
{
<Label Text="@($"Name = {Name}")"></Label>
}
<Label Text="@($"Version = {Version}")"></Label>
<Label Text="@($"Release Date = {ReleaseDate}")"></Label>
<Label Text="@($"Long = {Long}")"></Label>
<Label Text="@($"Double = {Double}")"></Label>
<Label Text="@($"Float = {Float}")"></Label>
<Label Text="@($"Decimal = {Decimal}")"></Label>
<Label Text="@($"Guid = {Guid}")"></Label>
<Label Text="@($"Guid? = {NullableGuid}")"></Label>
<Label Text="@($"Bool = {Bool}")"></Label>
<Label Text="@($"Query1 = Name:{Query1?.Name}, Value:{Query1?.Value}")"></Label>
<Label Text="@($"Query2 = Name:{Query2?.Name}, Value:{Query2?.Value}")"></Label>
</StackLayout>
</ContentPage>

@code {
[Parameter] public string Name { get; set; }
[Parameter] public int Version { get; set; }
[Parameter] public DateTime ReleaseDate { get; set; }
[Parameter] public long Long { get; set; }
[Parameter] public double Double { get; set; }
[Parameter] public float Float { get; set; }
[Parameter] public decimal Decimal { get; set; }
[Parameter] public Guid Guid { get; set; }
[Parameter] public Guid? NullableGuid { get; set; }
[Parameter] public bool Bool { get; set; }
[Parameter] public NavigationParameterModel Query1 { get; set; }
[Parameter] public NavigationParameterModel Query2 { get; set; }
}
5 changes: 3 additions & 2 deletions src/BlazorBindings.Maui/MauiAppBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ public static MauiAppBuilder UseMauiBlazorBindings(this MauiAppBuilder builder)

// Use factories for performance.
builder.Services
.AddSingleton<Navigation>(svcs => new Navigation(svcs))
.AddSingleton<Navigation>(svcs => new Navigation(svcs.GetRequiredService<MauiBlazorBindingsServiceProvider>()))
.AddSingleton<INavigation>(services => services.GetRequiredService<Navigation>())
.AddSingleton<MauiBlazorBindingsRenderer>(svcs => new MauiBlazorBindingsRenderer(svcs, svcs.GetRequiredService<ILoggerFactory>()));
.AddSingleton(svcs => new MauiBlazorBindingsRenderer(svcs.GetRequiredService<MauiBlazorBindingsServiceProvider>(), svcs.GetRequiredService<ILoggerFactory>()))
.AddSingleton(svcs => new MauiBlazorBindingsServiceProvider(svcs));

return builder;
}
Expand Down
14 changes: 14 additions & 0 deletions src/BlazorBindings.Maui/MauiBlazorBindingsRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ public MauiBlazorBindingsRenderer(IServiceProvider serviceProvider, ILoggerFacto
{
}

internal MauiBlazorBindingsRenderer(MauiBlazorBindingsServiceProvider serviceProvider, ILoggerFactory loggerFactory)
: base(serviceProvider, loggerFactory)
{
}

public override Dispatcher Dispatcher { get; } = new MauiDeviceDispatcher();

public Task AddComponent(Type componentType, MC.Application parent, Dictionary<string, object> parameters = null)
Expand Down Expand Up @@ -66,6 +71,15 @@ protected override ElementManager CreateNativeControlManager()
return (elements[0], addComponentTask);
}

internal async Task<(T Component, int ComponentId)> AddRootComponent<T>(Dictionary<string, object> initialParameters)
where T : IComponent
{
var component = (T)InstantiateComponent(typeof(T));
var componentId = AssignRootComponentId(component);
await RenderRootComponentAsync(componentId, ParameterView.FromDictionary(initialParameters));
return (component, componentId);
}

private async Task<(List<MC.BindableObject> Elements, Task<IComponent> Component)> GetElementsFromRenderedComponent(Type componentType, Dictionary<string, object> parameters)
{
var container = new RootContainerHandler();
Expand Down
31 changes: 31 additions & 0 deletions src/BlazorBindings.Maui/MauiBlazorBindingsServiceProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using BlazorBindings.Maui.UriNavigation;
using Microsoft.AspNetCore.Components.Routing;

namespace BlazorBindings.Maui;

// We cannot add Navigation services to common ServiceProvider as it leads to conflicts
// with Blazor navigation for hybrid apps.
// Therefore this wrapper is created to override those services for MBB cases only.
// Any better approach?...
internal class MauiBlazorBindingsServiceProvider : IServiceProvider
{
private readonly IServiceProvider _serviceProvider;
private NavigationManager _navigationManager;
private INavigationInterception _navigationInterception;

public MauiBlazorBindingsServiceProvider(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}

public object GetService(Type serviceType)
{
if (serviceType == typeof(NavigationManager))
return _navigationManager ??= new MbbNavigationManager();

if (serviceType == typeof(INavigationInterception))
return _navigationInterception ??= new MbbNavigationInterception();

return _serviceProvider.GetService(serviceType);
}
}
Loading