Dreamescaper / BlazorBindings.Maui

MAUI Blazor Bindings - Build native and hybrid MAUI apps with Blazor
MIT License
242 stars 16 forks source link

Cannot to get CascadingParam when naviated from INavigation.PushAsync<>() #90

Closed le-nn closed 1 year ago

le-nn commented 1 year ago

Cannot to get CascadingParam when naviated from INavigation.PushAsync<>()

public record Theme {
    public string Background { get; init; } = ""#ffffffff";
}

AppShell

<CascadingValue Value="Theme">
    <Shell FlyoutIsPresented="true">
        <ShellContent Title="Navigation">
            <PageNavigatedFrom />
        </ShellContent>
        <ShellContent Title="Navigation">
            <PageNavigatedTo />
        </ShellContent>
    </Shell>
</CascadingValue>

@code {
    Theme Theme { get; } = new();
}

PageNavigateFrom

@inject INavigation Navigation

<ContentPage Padding="12"
             Title="">
    <Button Text="Navigate" OnClick="HandleNavigate" />
</ContentPage>

@code {
    [CascadingParameter]
    Theme? Theme { get; set; }

    void HandleNavigate() {
        Navigation.PushAsync<PageNavigatedTo>();
    }
}

PageNavigateTo

<ContentPage Padding="12"
             Title="">
    <Label Text="@Theme?.Background.ToString()" />
</ContentPage>

@code {
    [CascadingParameter]
    Theme? Theme { get; set; } // Always null
}
Dreamescaper commented 1 year ago

That's an interesting use case.

Currently Navigation.PushAsync is equivalent to smth like that from Maui: Navigation.PushAsync(new PageNavigatedTo()), i.e. it always creates a new page, in a separate blazor render tree. It doesn't re-use <ShellContent Title="Navigation"> <PageNavigatedTo /> </ShellContent> in your Shell file.

I'll take a look whether it is possible to re-use cascading values from calling component (I doubt it that Blazor allows that, but not sure).

I'm thinking about your use case though. Would it work if you register Theme as a singleton in DI container instead of CascadingValue?

le-nn commented 1 year ago

In my usecase, If registering Singleton in DI instead of Cascading Param, I should handle StatehasChanged manually in every component with something like IObservable. So, I need CascadingValue. (ex: Changing the App Theme)

When route from nav menu button in Shell with ShellContent , it worked fine.

Dreamescaper commented 1 year ago

I see. Technically it is possible to handle StateHasChanged in root component only, but again - PushAsync currently creates a separate blazor tree, therefore there is no shared root component.

le-nn commented 1 year ago

I will deal with using a state management library like Fluxor. Thanks.

Dreamescaper commented 1 year ago

@le-nn I'm thinking to add a support for layout components. While it doesn't make much sense to define markup there, but it might be useful for cascading values or error boundaries.

Do you think it would make sense from the perspective of this request?

OTOH, since adding a markup in a layout doesn't make any sense (and probably won't work at all), maybe it makes sense to create a similar concept with a different name to avoid confusion.