如何在Blazor页面之间传递对象

6

我有一个主页面,在这个页面上有一个对象列表。使用foreach获取它的项,当你点击按钮时,我想传递该项到另一个页面。我如何传递?


在Blazor应用程序状态方面进行一些搜索 - 这是一个很好的介绍。在Blazor中处理状态有许多方法 - 您可以选择适合您项目的方法。 - Mister Magoo
由于您的问题缺乏代码,我建议您需要使用作用域服务来保存对象集合,可能是一个带有整数键的IDictionary,您将其传递给新页面 - newpage/1。然后,NewPage使用1从服务中检索特定对象。请参阅MSDocs有关服务的信息 - https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/dependency-injection?view=aspnetcore-5.0&pivots=webassembly - MrC aka Shaun Curtis
1
最简单的答案是——不要导航。我建议只在需要移动到应用程序的另一个部分时进行导航(即不需要传递任何数据的部分)。显示一个控件来展示你的项目。 - Bennyboy1973
2个回答

6
如果这是一个简单的值 (如 int, string),你可以将该值作为路径参数或查询参数传递到其他页面:
来自页面:
<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>

转至页面:

@page "/page/{PathParam}"

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

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

然而,如果数据更为复杂,请尝试使用此处描述的选项之一:https://learn.microsoft.com/en-us/aspnet/core/blazor/state-management?view=aspnetcore-5.0&pivots=webassembly服务器端存储浏览器存储内存状态容器服务


谢谢您的帮助。我使用了我的对象中的ID,以便在其他页面上使用它。 - XDboy

2
关于更复杂的对象,最好使用StateContainer(内存解决方案)。
MauiProgram.cs中注册您的StateContainer,如下所示:
builder.Services.AddSingleton<StateContainer>();

其中 StateContainer.cs 包含:

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

然后,只是举个例子,我将创建一个名为ComplexObject.cs的文件。

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

当你有页面,例如Index.razorCounter.razor,并且你想要从一个页面发送ComplexObject到另一个页面时,在Index.razor中注入StateContainer,然后调用类似以下的方法:
public void OpenCounterWithData()
{
    var data = new ComplexObject{Count = 3, Color="red"}
    _stateContainer.ObjectTunnel.Add(data.GetHashCode(), data)

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

Counter.razor中,您可以指定页面如下:
@page "/counter/{SetHashCode:int}"

和输入参数:

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

OnInitialized中,你可以从StateContainer中提取值,例如:
protected override void OnInitialized()
{
    var data = (ComplexObject) _stateContainer.ObjectTunnel[SetHashCode];
}

在那之后,您还应该从ObjectTunnel中移除该对象。这基本上是整个流程。

优化:

  • 我创建了一些扩展方法来优化流程

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);
    }
}

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;
    }
}

使用这些扩展方法,你可以选择这样做。
_stateContainer.ObjectTunnel.Add(data.GetHashCode(), data)

只使用:

_stateContainer.AddRoutingObjectParameter(_trainingSet);

而不是:
var data = (ComplexObject) _stateContainer.ObjectTunnel[SetHashCode];
_stateContainer.ObjectTunnel.Remove(SetHashCode);

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

您先生是真正的MVP,这个解决方案绝对是一种绝妙的杰作。 - undefined
1
我认为StateContainer应该是Scoped而不是Singleton。我尝试了Scoped,对我来说很有效。Singleton可能会导致内存溢出。 - undefined
1
@RamilAliyev007 是和不是。Blazor的类型(服务器 vs WASM)很重要。因为在WASM中,Singleton=Scoped。对于Blazor服务器来说,将其设置为Scoped是正确的做法,这样状态容器就可以按用户/电路使用,而不是跨所有用户。谢谢你的提醒。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接