Blazor 的动态组件

问题描述 投票:0回答:1

我创建了这个通用组件,以便能够传递列表或网格视图的模板 @* 使用说明:

    The DynamicProductDisplay dynamically displays items in either a grid or list layout, depending on the user's selection.
    Pass a list of items to the `Items` parameter. Use the `GridViewTemplate` and `ListViewTemplate` parameters to specify
    how each item should be rendered in grid or list view respectively.

    To use DynamicProductDisplay with `GridProduct` and `ListedProduct`, define render fragments like this:

    <DynamicProductDisplay Items="products"
                         GridViewTemplate="product => @<GridProduct
                            Name="product.Name"
                            ImageSource="product.ImageSource"
                            Description="product.Description"
                            Price="product.Price"
                            OnAddToCart="() => AddToCart(product)"
                            OnAddToFavorites="() => AddToFavorites(product)" />"
                         ListViewTemplate="product => @<ListedProduct
                            Name="product.Name"
                            ImageSource="product.ImageSource"
                            Description="product.Description"
                            Price="product.Price"
                            OnAddToCart="() => AddToCart(product)"
                            OnAddToFavorites="() => AddToFavorites(product)" />"
                         GridColumnClass="col-md-4"
                         ListColumnClass="col-12" />

    Replace `AddToCart` and `AddToFavorites` with your own event handlers.

    Parameters:
    - `Items`: The list of items to display.
    - `GridViewTemplate`: Render fragment defining how each item is rendered in grid view.
    - `ListViewTemplate`: Render fragment defining how each item is rendered in list view.
    - `GridColumnClass`: CSS class for grid layout columns.
    - `ListColumnClass`: CSS class for list layout columns.
*@

@typeparam TItem

<div class="d-flex justify-content-end mb-3">
    <MudToggleIconButton @bind-Toggled="isGridView"
                         Icon="@Icons.Material.Filled.GridView"
                         ToggledIcon="@Icons.Material.Filled.ViewList"
                         title="@buttonTitle" />
</div>

    
<div class="row">
    @if (Items != null)
    {        
        @foreach (var item in Items!)
        {
            <div class="@gridOrListClass">
                @if (isGridView)
                {
                    @GridViewTemplate(item);
                }
                else
                {
                    @ListViewTemplate(item);
                }
            </div>
        }
    }
</div>
    

@code {
    [Parameter] public List<TItem>? Items { get; set; }

    [Parameter] public bool isGridView { get; set; } = true;

    [Parameter] public RenderFragment<TItem>? GridViewTemplate { get; set; }
    [Parameter] public RenderFragment<TItem>? ListViewTemplate { get; set; }

    [Parameter] public string GridColumnClass { get; set; } = "col-md-4";
    [Parameter] public string ListColumnClass { get; set; } = "col-12";
    
    private string gridOrListClass => isGridView ? GridColumnClass : ListColumnClass;
    private string buttonTitle => isGridView ? "List View" : "Grid View";
}

我的模板如下所示: 网格->

@typeparam TItem
@inherits ComponentBase

@* Summary of Usage:
   To use the GridProduct component, pass in the product's Name, ImageSource, Description, and Price as parameters.
   Optionally, set MaxDescriptionLength to control the displayed length of the Description.
   Provide EventCallback handlers for OnAddToCart and OnAddToFavorites to handle button clicks.

   Example usage:

   <GridProduct
       Name="product.Name"
       ImageSource="product.ImageSource"
       Description="product.Description"
       Price="product.Price"
       MaxDescriptionLength="50"
       OnAddToCart="() => AddToCart(product)"
       OnAddToFavorites="() => AddToFavorites(product)" />
*@

<MudCard Class="m-2 p-2" Elevation="2">
    <!-- Product image at the top -->
    <MudCardMedia Image="@ImageSource" Alt="@Name" Class="product-image" Height="200" />

    <!-- Product name as title -->
    <MudCardContent>
        <MudText Typo="Typo.h6" Class="text-center">@Name</MudText>

        <!-- Description with adjustable length -->
        <MudText Typo="Typo.body2" Class="product-description text-center mt-1">
            @DescriptionSubstring
        </MudText>

        <!-- Product price -->
        <MudText Typo="Typo.h6" Class="product-price text-center mt-1" Color="Color.Primary">
            @Price.ToString("C")
        </MudText>
    </MudCardContent>

    <!-- Action buttons at the bottom of the card -->
    <MudCardActions Class="d-flex justify-space-between">
        <MudButton Variant="Variant.Filled" Color="Color.Secondary" OnClick="@AddToCart">
            Add to Cart
        </MudButton>
        <MudButton Variant="Variant.Outlined" Color="Color.Tertiary" OnClick="@AddToFavorites">
            Add to Favorites
        </MudButton>
    </MudCardActions>
</MudCard>

@code {
    [Parameter] public string Name { get; set; } = string.Empty;
    [Parameter] public string ImageSource { get; set; } = string.Empty;
    [Parameter] public string Description { get; set; } = string.Empty;
    [Parameter] public decimal Price { get; set; }
    [Parameter] public int MaxDescriptionLength { get; set; } = 100;
    [Parameter] public EventCallback OnAddToCart { get; set; }
    [Parameter] public EventCallback OnAddToFavorites { get; set; }

    private string DescriptionSubstring => Description.Length > MaxDescriptionLength
        ? $"{Description.Substring(0, MaxDescriptionLength)}..."
        : Description;

    private Task AddToCart() => OnAddToCart.InvokeAsync(null);
    private Task AddToFavorites() => OnAddToFavorites.InvokeAsync(null);
}

列表->

@* Summary of Usage:
   To use the ListedProduct component, pass in the product's Name, ImageSource, Description, and Price as parameters.
   Optionally, set MaxDescriptionLength to control the displayed length of the Description.
   Provide EventCallback handlers for OnAddToCart and OnAddToFavorites to handle button clicks.

   Example usage:

   <ListedProduct
       Name="product.Name"
       ImageSource="product.ImageSource"
       Description="product.Description"
       Price="product.Price"
       MaxDescriptionLength="50"
       OnAddToCart="() => AddToCart(product)"
       OnAddToFavorites="() => AddToFavorites(product)" />
*@

@typeparam TItem
@inherits ComponentBase

<!-- The outer container using MudBlazor's MudPaper for styling and elevation -->
<MudPaper Class="p-2 m-2" Elevation="1">
    <MudGrid>
        <!-- Left section of the grid to display the product image -->
        <MudItem xs="12" sm="4">
            <MudImage Src="@ImageSource" Alt="@Name" Class="product-image" />
        </MudItem>

        <!-- Right section of the grid for product details -->
        <MudItem xs="12" sm="8">
            <MudText Typo="Typo.h6">@Name</MudText>

            <!-- Displaying a limited description with customizable length -->
            <MudText Typo="Typo.body2" Class="product-description">
                @DescriptionSubstring
            </MudText>

            <!-- Displaying the product price in bold and primary color -->
            <MudText Typo="Typo.h6" Class="product-price" Color="Color.Primary">
                @Price.ToString("C")
            </MudText>

            <!-- Buttons for adding to cart and to favorites, invoking passed event callbacks -->
            <MudButton Variant="Variant.Filled" Color="Color.Secondary" OnClick="@AddToCart">Add to Cart</MudButton>
            <MudButton Variant="Variant.Outlined" Color="Color.Tertiary" OnClick="@AddToFavorites">Add to Favorites</MudButton>
        </MudItem>
    </MudGrid>
</MudPaper>

@code {
    /// <summary>
    /// 
    /// </summary>
    [Parameter] public string Name { get; set; } = string.Empty;
    [Parameter] public string ImageSource { get; set; } = string.Empty;
    [Parameter] public string Description { get; set; } = string.Empty;
    [Parameter] public decimal Price { get; set; }
    [Parameter] public int MaxDescriptionLength { get; set; } = 100;
    [Parameter] public EventCallback OnAddToCart { get; set; }
    [Parameter] public EventCallback OnAddToFavorites { get; set; }

    private string DescriptionSubstring => Description.Length > MaxDescriptionLength ? $"{Description.Substring(0, MaxDescriptionLength)}..." : Description;

    private Task AddToCart() => OnAddToCart.InvokeAsync(null);
    private Task AddToFavorites() => OnAddToFavorites.InvokeAsync(null);

}

我就是无法让它工作。

我的方法是错误的还是我遗漏了什么?

我想象做这样的事情:

@page "/products-display"
@aBunchOfUsings

<DynamicProductDisplay
    TItem="ProductsDetailsListingModel"
    Items="SampleProducts.Products"
    GridViewTemplate="product => @<GridProduct 
        Name='product.Name'
        ImageSource='product.ImageSource'
        Description='product.Description'
        Price='product.Price'
        OnAddToCart='() => AddToCart(product)'
        OnAddToFavorites='() => AddToFavorites(product)' />"
    ListViewTemplate="product => @<ListedProduct 
        Name='product.Name'
        ImageSource='product.ImageSource'
        Description='product.Description'
        Price='product.Price'
        OnAddToCart='() => AddToCart(product)'
        OnAddToFavorites='() => AddToFavorites(product)' />"
/>

@code {
}

重点是我希望保持组件的通用性和类型不可知性以便重用。要么是我在使用组件时弄乱了语法,要么是其他什么东西,我在编程方面相当新,所以不要害怕纠正任何东西。

c# razor blazor
1个回答
0
投票

你正在做一些有点奇怪的事情 - 至少对我来说 - 我会采取更传统的方法在标记中设置模板:

<DynamicProductDisplay
    TItem="ProductsDetailsListingModel"
    Items="SampleProducts.Products">

      <GridViewTemplate Context="product">
        <GridProduct 
            Name='product.Name'
            ImageSource='product.ImageSource'
            Description='product.Description'
            Price='product.Price'
            OnAddToCart='() => AddToCart(product)'
            OnAddToFavorites='() => AddToFavorites(product)' />
      </GridViewTemplate>

      <ListViewTemplate Context="product">
          <ListedProduct 
            Name='product.Name'
            ImageSource='product.ImageSource'
            Description='product.Description'
            Price='product.Price'
            OnAddToCart='() => AddToCart(product)'
            OnAddToFavorites='() => AddToFavorites(product)' />
      </ListViewTemplate>

</DynamicProductDisplay>

如果您遇到错误,请列出它们 - 这就是我所能提供的帮助,无需更多细节或简单的可重现示例

© www.soinside.com 2019 - 2024. All rights reserved.