Blazor CascadingValue的限制是什么?无法传递复杂对象。

huangapple go评论94阅读模式
英文:

What are the limitations of Blazor CascadingValue? Complex objects are not being passed

问题

我有一个IClipboardService,我将其注入到组件中,但由于只会有一个,我决定尝试使用CascadingValue

我在一个基本的WebAssembly Blazor应用程序中重新创建了所有这些内容。只需将以下更改添加到其中:

我创建了一个名为CascadingClipboard.razor的组件,内容如下:

  1. <CascadingValue Value="_clipboardService">
  2. @ChildContent
  3. </CascadingValue>
  4. @inject ClipboardService _clipboardService
  5. @code {
  6. [Parameter]
  7. public RenderFragment ChildContent { get; set; }
  8. }

我还创建了一个更简单的测试组件CascadingInt.razor,它包含一个int值:

  1. <CascadingValue IsFixed=true Value="_int">
  2. @ChildContent
  3. </CascadingValue>
  4. @code {
  5. [Parameter]
  6. public RenderFragment ChildContent { get; set; }
  7. public int _int { get; set; } = 123;
  8. }

然后,我用这两个组件包装了MainLayout.razor

  1. @inherits LayoutComponentBase
  2. <CascadingClipboard>
  3. <CascadingInt>
  4. <div class="page">
  5. <div class="sidebar">
  6. <NavMenu />
  7. </div>
  8. <main>
  9. <div class="top-row px-4">
  10. <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
  11. </div>
  12. <article class="content px-4">
  13. @Body
  14. </article>
  15. </main>
  16. </div>
  17. </CascadingInt>
  18. </CascadingClipboard>

Index.razor中添加了接收CascadingParameters

  1. @page "/"
  2. <PageTitle>Index</PageTitle>
  3. <h1>Hello, world!</h1>
  4. Welcome to your new app.
  5. <SurveyPrompt Title="How is Blazor working for you?" />
  6. @code{
  7. [CascadingParameter]
  8. public CascadingClipboard _cascadingClipboard { get; set; }
  9. [CascadingParameter]
  10. public int IntValue { get; set; }
  11. protected override async Task OnParametersSetAsync()
  12. {
  13. // 在此设置断点以检查值
  14. await base.OnParametersSetAsync();
  15. }
  16. }

简单值始终存在,但复杂对象始终为null

我尝试过使用显式赋值而不是注入,但没有任何区别。

这是否只是Blazor CascadingValues的一个限制?

更多信息:

我之所以首先尝试这样做,是因为我的剪贴板单例需要从本地存储中初始化(以便在刷新后或稍后返回时保持状态)。使用Cascading组件可以很容易地实现这一点,但将机制保留为一个可注入的服务意味着我仍然可以将其注入到非组件中(而Cascading只能与组件一起使用)。现在我有了一个同时具有两者优点的模式。

英文:

I have an IClipboardService I was injecting into components, but as there is only ever one, I decided to try using a CascadingValue instead.

I recreated all this in a minimal test case. Just add these changes to a basic WebAssembly Blazor app:

I created a CascadingClipboard.razor component that looks like this

  1. &lt;CascadingValue Value=&quot;_clipboardService&quot;&gt;
  2. @ChildContent
  3. &lt;/CascadingValue&gt;
  4. @inject ClipboardService _clipboardService
  5. @code {
  6. [Parameter]
  7. public RenderFragment ChildContent { get; set; }
  8. }

I also created a far simpler test CascadingInt.razor component with an int value

  1. &lt;CascadingValue IsFixed=true Value=&quot;_int&quot;&gt;
  2. @ChildContent
  3. &lt;/CascadingValue&gt;
  4. @code {
  5. [Parameter]
  6. public RenderFragment ChildContent { get; set; }
  7. public int _int { get; set; } = 123;
  8. }

I wrapped the MainLayout.razor with both:

  1. @inherits LayoutComponentBase
  2. &lt;CascadingClipboard&gt;
  3. &lt;CascadingInt&gt;
  4. &lt;div class=&quot;page&quot;&gt;
  5. &lt;div class=&quot;sidebar&quot;&gt;
  6. &lt;NavMenu /&gt;
  7. &lt;/div&gt;
  8. &lt;main&gt;
  9. &lt;div class=&quot;top-row px-4&quot;&gt;
  10. &lt;a href=&quot;https://docs.microsoft.com/aspnet/&quot; target=&quot;_blank&quot;&gt;About&lt;/a&gt;
  11. &lt;/div&gt;
  12. &lt;article class=&quot;content px-4&quot;&gt;
  13. @Body
  14. &lt;/article&gt;
  15. &lt;/main&gt;
  16. &lt;/div&gt;
  17. &lt;/CascadingInt&gt;
  18. &lt;/CascadingClipboard&gt;

Added receiving CascadingParameters in Index.razor

  1. @page &quot;/&quot;
  2. &lt;PageTitle&gt;Index&lt;/PageTitle&gt;
  3. &lt;h1&gt;Hello, world!&lt;/h1&gt;
  4. Welcome to your new app.
  5. &lt;SurveyPrompt Title=&quot;How is Blazor working for you?&quot; /&gt;
  6. @code{
  7. [CascadingParameter]
  8. public CascadingClipboard _cascadingClipboard { get; set; }
  9. [CascadingParameter]
  10. public int IntValue { get; set; }
  11. protected override async Task OnParametersSetAsync()
  12. {
  13. // BREAKPOINT HERE TO CHECK VALUES
  14. await base.OnParametersSetAsync();
  15. }
  16. }

The simple value is always present. The complex object is always null.

I have tried using an explicit assignment instead of injection, but no difference.

Is this simply a limitation of Blazor CascadingValues?

More info:

The reason I tried this in the first place, is that my clipboard singleton needed to be initialised from local storage (to happily survive a refresh, or even returning later). Having a Cascading component makes that easy, but leaving the mechanics as a separate injectable service means I can still inject it into non-components (whereas Cascading only works with components). I now have a pattern for the best of both worlds.

答案1

得分: 3

我觉得有点傻,但这可能对其他人有帮助:

CascadingValue 分配给 CascadingParameter 与 C# 中的 as 强制转换类似。如果值的类型不匹配,它将为 null。

如果你看我的示例,它有与我的原始应用程序中一样的拼写错误,实际上我试图将 ClipboardService 对象分配给 CascadingClipboard 参数。

不要总是相信智能感知 Blazor CascadingValue的限制是什么?无法传递复杂对象。

英文:

I feel like a bit of an idiot, but this may help someone else:

Assignment of a CascadingValue to a CascadingParameter works similar to as casting in C#. If the value types do not match it will be null.

If you look at my example, it had the same typo as in my original app, I was effectively trying to assign a ClipboardService object to a CascadingClipboard parameter.

It does not pay to trust Intellisence all the time Blazor CascadingValue的限制是什么?无法传递复杂对象。

huangapple
  • 本文由 发表于 2023年7月27日 22:39:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76780857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定