【问题标题】:One-way [Parameter] binding programatically以编程方式单向 [Parameter] 绑定
【发布时间】:2021-07-20 10:40:41
【问题描述】:

我想为第三方组件的参数设置默认值。说我有这个:

myBasePage.cs:

public class MyBasePage : ComponentBase
{
  public IEnumerable MyData { get; set; }
}

myPage.razor:

@inherits MyBasePage
<ThirdPartyComponent Data="@MyData" />

由于ThirdPartyComponent 上的Data 是带有DataHasChanged() 虚拟方法的[Parameter],因此通过像这样渲染blazor 组件,我将获得单向绑定,如果我更改我的MyData页面,以编程方式,组件将更新。 这会很好。

现在,假设我无法修改 ThirdPartyComponent,但我想根据我的基本页面在其中设置一些默认值......就像这样:

myPage.razor:

@inherits MyBasePage
<MyDerivedComponent PageComponent="@this" />

myDerivedComponent.cs:

public class MyDerivedComponent : ThirdPartyComponent 
{
   [Parameter] public MyBasePage PageComponent { get; set; }
   public override void OnInitialized()
   {
      /* Set other parameter defaults */
      this.OtherParameter = 10;

      /* Bind to Data, as if I was passing it as a parameter in the Razor template */
      this.Data = PageComponent.MyData;
   }
}

这一行:

this.Data = PageComponent.MyData;

根本不创建绑定(如果我修改 MyData,则 blazor 组件不会得到更新)。有没有办法以编程方式创建它?

注意:真正的ThirdPartyComponent 不仅包括大量参数,还包括模板等。出于多种原因,我希望MyDerivedComponent 是派生类型,而不是带有ThirdPartyComponent 子代的“父组件”,如果可能的话)。

【问题讨论】:

  • 我认为Data="@MyData" 不会在MyData 更改时重新呈现页面。您是否会更改其值作为对某些事件的响应?
  • @PharazFadaei 它不会自动发生,但如果您执行 StateHasChanged 或者它是 EventCallback,它会自动执行。如果我以编程方式设置它(不在 razor 组件模板上),它也不会。
  • @PharazFadaei 也​​就是说,如果我这样做&lt;MyDerivedComponent Data="@this.Data"&gt;,它会按预期工作......如果我通过代码设置它(&lt;MyDerivedComponent PageComponent="@this"&gt;,然后是this.Data = PageComponent.Data;),它不会跨度>
  • 你的意思是如果你只做Data="@this.Data"然后改变this.Data的值组件会自动重新渲染?
  • 假设您在MyBasePage 上调用StateHasChangedData 的值发生变化,MyBasePage 组件将相应地重新呈现。 MyDerivedComponentMyBasePage 的子代,具有复杂类型参数 (PageComponent),因此其 OnParametersSet 将基于 the docs 调用。

标签: c# blazor blazor-server-side


【解决方案1】:

这应该可行:

public class MyDerivedComponent : ThirdPartyComponent 
{
   [Parameter] public MyBasePage PageComponent { get; set; }
   public override void OnInitialized()
   {
      /* Set other parameter defaults */
      this.OtherParameter = 10;


      //this.Data = PageComponent.MyData;
   }
}

 protected override void OnParametersSet()   
 {
    Data = Data ?? PageComponent?.MyData ;  // determine priority
    base.OnParametersSet();
 }

OnParametersSet() 通知组件它有新的参数。派生最多的类可以在这里介入。

但是当this.MyData 发生变化时,没有简单的解决方案,这对 Blazor 来说是看不见的。

【讨论】:

  • 这在PageComponent.Data 更改时不起作用,组件上没有更改任何参数,因为根本没有对Data 的绑定订阅,所以它不会调用OnParameterSet,除非我改变了整个PageComponent
  • 查看 Blazor 的来源,似乎 RenderTreeBuilder 在绑定时(在渲染时)使用键号“订阅”绑定的属性,因此它会查找状态更改的更改.但所有这些都是内部的(并且依赖于实现),而且我无法访问已编译的渲染树,所以我认为我在这里不走运。
  • 是的,没错。也许我误读了“根本不创建绑定”。
  • 但是PageComponent是复杂类型,应该假设有变化吧?
【解决方案2】:

有没有办法以编程方式创建它?当然,但这并不意味着你应该这样做。

参数不应在组件代码中设置或操作。每当SetParametersAsyncRenderer 调用时,就会在外部设置参数。如果您在内部更改它们,则会创建两个版本的事实。

【讨论】:

    猜你喜欢
    • 2021-06-18
    • 2012-12-03
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2011-05-08
    • 2017-04-04
    • 1970-01-01
    相关资源
    最近更新 更多