深入浅出Blazor webassembly之使用EventCallback机制进行组件之间联动

===============================

总体思路

===============================

设想一个购物车的场景,对于购物车中的某个商品, 如果增加数量, 购物车总数量也要同步增加.

使用CascadingValue组件就无法实现这个要求, CascadingValue组件智能实现从上层组件传值到下层组件, 反向传值是不行的.   EventCallback 因为有更高的灵活性, 能实现这样的功能,

总体思路:

⒈ 在事件源组件中定义一个 EventCallback<> 委托属性, 并将这个属性加上 Parameter 注解. 这是事件埋点, 关注该事件的其他组件必须注入一个Callback委托.

    需要说明的是Blazor的 EventCallback<> 是单播 single cast 事件,  而 .Net 事件是多播. 

   代码示例:  [Parameter] public EventCallback<MouseEventArgs> OnNumberAdded{ get; set;}

2. 在事件源组件的Trigger点, 进行委托调用

  代码示例:  await OnNumberAdded.InvokeAsync(e)

3. 在事件订阅方组件中, 为事件源组件注入一个埋点事件委托.

  代码示例: <ProductItemUI ProductItem="product" OnNumberAdded="OnNumberAddedHandler"/>

===============================

完整示例:

===============================

ProductItem Data对象代码

//===========================
// file: DataProductItem.cs
//===========================
namespace blazorDemo1.Data
{
    public class ProductItem
    {
        public string Title{get ;set ;}
        public int Quantity{get ;set ;}
    }
}

ProductItemUI 组件代码, 在组件中增加埋点Parameter, 并触发埋点委托

@* //================================ *@
@* // file: SharedProductItemUI.razor *@
@* //================================= *@
@using blazorDemo1.Data 

<tr>
    <td>@ProductItem.Title</td>
    <td>@ProductItem.Quantity</td>
    <td>
        <button type="button" class="btn btn-success btn-sm" @onclick="AddNumber">Add 1</button>
    </td>
</tr>
@code{
    [Parameter] public ProductItem ProductItem {get ;set ;}
    [Parameter] public EventCallback<MouseEventArgs> OnNumberAdded{get ;set ;}
        public async Task AddNumber(MouseEventArgs e){
            ProductItem.Quantity+=1 ;
            await OnNumberAdded.InvokeAsync(e) ; //在加1完成后, 触发埋点事件
        } 
}

Cart 购物车组件, 注入埋点委托

@* //================================ *@
@* // file: PagesCart.razor *@
@* //================================= *@
@page "/cart"
@using blazorDemo1.Data

<div class="row">
    <div class="col">
        <h3>Buy Item List</h3>
    </div>
    <div class="col">
        <h5 class="float-right"> Total Qty:@TotalQuantity</h5>
    </div>
</div>
<br>
<table class="table">
    <tr>
        <th>Title</th>
        <th> Qty</th>
        <th></th>
    </tr>
    @foreach (var Product in Products)
    {
        <ProductItemUI ProductItem="@Product" OnNumberAdded="@OnNumberAddedHandler"></ProductItemUI>
    }
</table>

@code {
    public List<ProductItem> Products;
    public int TotalQuantity;
    protected override void OnInitialized()
    {
        Products = new List<ProductItem>(){
        new ProductItem(){Title="A", Quantity=10},
        new ProductItem(){Title="B", Quantity=20},
        new ProductItem(){Title="C", Quantity=30}
    };
        UpdateTotalQty();
    }
    void UpdateTotalQty()
    {
        TotalQuantity = Products.Sum(i => i.Quantity);
    }

    void OnNumberAddedHandler(MouseEventArgs e)
    {
        TotalQuantity = Products.Sum(i => i.Quantity);
    }
}

原文地址:https://www.cnblogs.com/harrychinese/p/blazor-eventcallback.html