XDboy
XDboy

Reputation: 169

How to pass objects between Pages in Blazor

I have my main page and in this page I have a list with objects. With a foreach I get the items of it and I want to pass the item to another page if you click the button. How can I pass it?

Upvotes: 7

Views: 23082

Answers (2)

Kebechet
Kebechet

Reputation: 2377

Regarding more complex objects it is good to use StateContainer (in memory solution).

Register your StateContainer in MauiProgram.cs like:

builder.Services.AddScoped<StateContainer>();

where StateContainer.cs contains:

public readonly Dictionary<int, object> ObjectTunnel = new();

then just as an example I will create ComplexObject.cs where

public class ComplexObject
{
    public int Count = 0;
    public string Color = string.Empty;
}

then when you have pages e.g. Index.razor and Counter.razor and you would like to send ComplexObject from one the the other, then in Index.razor inject StateContainer

and call something like:

public void OpenCounterWithData()
{
    var data = new ComplexObject{Count = 3, Color="red"}
    _stateContainer.ObjectTunnel.Add(data.GetHashCode(), data)

    _navigationManager.Navigate($"counter/{data.GetHashCode()}")
}

and In Counter.razor you specify page like:

@page "/counter/{SetHashCode:int}"

and Input parameter:

[Parameter] public int SetHashCode { get; set; }

and e.g. in OnInitialized you can extract the value from StateContainer like:

protected override void OnInitialized()
{
    var data = (ComplexObject) _stateContainer.ObjectTunnel[SetHashCode];
}

after that you should also remove the object from the ObjectTunnel. This is basically the whole flow.


Optimizations:

  • I have created a few extension methods to optimize the flow

StateContainerExtensions.cs

public static class StateContainerExtensions
{
    public static int AddRoutingObjectParameter(this StateContainer stateContainer, object value)
    {
        stateContainer.ObjectTunnel[value.GetHashCode()] = value;
        return value.GetHashCode();
    }

    public static T GetRoutingObjectParameter<T>(this StateContainer stateContainer, int hashCode)
    {
        return (T) stateContainer.ObjectTunnel.PopValue(hashCode);
    }
}

and DictionaryExtensions.cs

public static class DictionaryExtensions
{
    public static TValue PopValue<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey keyName) where TKey : notnull
    {
        var value = dictionary[keyName];
        dictionary.Remove(keyName);
        return value;
    }
}

With those extension methods you can instead

_stateContainer.ObjectTunnel.Add(data.GetHashCode(), data)

use just:

_stateContainer.AddRoutingObjectParameter(data);

and instead:

var data = (ComplexObject) _stateContainer.ObjectTunnel[SetHashCode];
_stateContainer.ObjectTunnel.Remove(SetHashCode);

use:

var data = _stateContainer.GetRoutingObjectParameter<ComplexObject>(SetHashCode);

Upvotes: 14

Bart Kiers
Bart Kiers

Reputation: 170158

If it's a simple value (int, string) then you could just pass this value as a path- or query param to the other page:

From page:

<ul>
  <li><a href="/page/a">A</a></li>
  <li><a href="/page/b">B</a></li>
  <li><a href="/page/c">C</a></li>
</ul>

to page:

@page "/page/{PathParam}"

<h1>Page @this.PathParam</h1>

@code {
  [Parameter]
  public string PathParam { get; set; }
}

However, if the data is more complex, try using one of the options described in here: https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-5.0&pivots=webassembly (Server-side storage, Browser storage or In-memory state container service)

Upvotes: 7

Related Questions