Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.9k views
in Technique[技术] by (71.8m points)

c# - Passing interfaces instead of concrete classes into @ChildContent's [CascadingParameter] using <CascadingValue> in blazor

I have Item implementing IItem, and ItemContainer implementing IItemContainer.

In ItemContainer.razor I have the following, passing itself to all its @ChildContent:

<CascadingValue Value="this">
    @ChildContent
</CascadingValue>

@code{
  List<IItem> Items;
  void AddItem(IItem item) => Items.Add(item);
  .
  .
  .
}

And in the Item class I have the following:

[CascadingParameter] public IItemContainer ItemContainer {get;set;}
protected override void OnInitialized()
{
  ItemContainer.AddItem(this);
}
RenderFragment RenderStuff => Do some rendering stuff with ItemContainer
.
.
.

Say that I have the following:

<ItemContainer>
  <Item>
  <Item>
  <Item>
</ItemContainer>

I expect that by the time the first <Item> calls its OnInitialized, the <ItemContainer> would already have passed itself into [CascadingParameter] public IItemContainer ItemContainer {get;set;}, so [CascadingParameter] public IItemContainer ItemContainer {get;set;} will not be null, and ItemContainer.AddItem(this); will be successfully called and add the <Item> to the <ItemContainer>'s List<IItem> Items.

This is not an issue if I use concrete classes, i.e. ItemContainer instead of IItemContainer for <CascadingValue Value="this">.

However, when the this of <CascadingValue Value="this"> is an interface and not an concrete class, casting does not automatically happen, and null exception will be thrown (ItemContainer not passed into the cascading param).

And when I try to cast it using <CascadingValue TValue="IItemContainer" Value="(IItemContainer)this">, exception will be thrown.

I want to pass interfaces instead of concrete classes into cascading params. Is there a way to make this work?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

And when I try to cast it using

<CascadingValue TValue="IItemContainer" 
  Value="(IItemContainer)this">

exception will be thrown.

You don't do that like this. You still have to pass this

Here's the way to do that:

ItemContainer.razor

<CascadingValue Value="this">
    @ChildContent
</CascadingValue>

@code{
  List<IItem> Items;
  void AddItem(IItem item) => Items.Add(item);
  .
  .
  .
}

Item.razor

@implements IItem
 
[CascadingParameter] public IItemContainer ItemContainer {get;set;}

protected override void OnInitialized()
{
    // Note: The first ItemContainer (left to right) is the class name,
    // the second is the name of the cascading parameter property. If the compiler
    // fail to recognize that (I guess she won't), change this property to 
    // ContainerItemSet, as for instance. Otherwise, it should work perfectly 
    // fine. 
    ((ItemContainer)(object)(ItemContainer)).AddItem(this);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...