如何在循环中呈现组件列表(Blazor)?

7

我在使用Blazor时可能漏掉了很明显的东西…… 我想简单地呈现一个包含组件的列表,但没有(明显?)的方式来引用迭代器(它是一个组件),以便进行呈现?

TodoList.razor

<input @bind="_newTodo" />
<button @onclick="@AddTodoItem">+</button>

@foreach (TodoItem todoItem in _todoItems)
{
    // todoItem is a razor component, yet I can't simply render it here?
    // <todoItem />
}

@code {
    private IList<TodoItem> _todoItems = new List<TodoItem>();
    private string _newTodo;

    private void AddTodoItem()
    {
        if (!string.IsNullOrWhiteSpace(_newTodo))
        {
            _todoItems.Add(new TodoItem { Title = _newTodo });
            _newTodo = string.Empty;
        }
    }
}

TodoItem.razor

<span>@Title</span>

@code {
    public string Title { get; set; }
}
5个回答

5

实现这一点的方法之一是创建一个包含组件属性并将属性传递给它的类

<input @bind="_newTodo" />
<button @onclick="@AddTodoItem">+</button>

@foreach (TodoItem todoItem in _todoItemsDto)
{
    // Pass the Dto properties to the component
    <TodoItem Title="@todoItem.Title" />
}

@code {
    private IList<TodoItemDto> _todoItemsDto = new List<TodoItemDto>();
    private string _newTodo;

    class TodoItemDto {
        public string Title { get; set; }
    }

    private void AddTodoItem()
    {
        if (!string.IsNullOrWhiteSpace(_newTodo))
        {
            _todoItems.Add(new TodoItemDto { Title = _newTodo });
            _newTodo = string.Empty;
        }
    }
}

1
这是我在本地使用的解决方案之一 - 我真的希望有更好的解决方案。我将继续调查,如果找到更好的解决方案,我会自己回答。否则,这就是答案。 - mariocatch
@mariocatch 我也试过了,但目前为止...没什么好的结果。Blazor仍处于早期阶段,并缺少很多功能。我相信在未来他们会解决这个问题。 - Vencovsky
1
似乎Blazor团队表示,这将在2020年11月的.NET 5发布中推出:https://github.com/dotnet/aspnetcore/issues/5456#issuecomment-584219488 - mariocatch

0

这可能不是最佳方法,但它可以避免在标签中设置50多个属性。

组件:


  <h1>@Title</h1> 
  <h2>@Description</h2>


@code {
    public string? Title { get; set; }
    public string? Description { get; set; }
    
    [Parameter]
    public KanbanTask? Origin //KanbanTask is how I named this same component
    {
        get { return null; }
        set
        {
            Title = value?.Title;
            Description = value?.Description;
        }
    }
}

那么如何调用它:

   @foreach (var todoTask in TodoList)
            {
                <KanbanTask Origin="@todoTask" />
            }

这是使用属性集合的构造函数。它可以工作,但我认为它并不完美,因为set最初并不是为此而设计的。如果有人有更好的想法,我很感兴趣。


0
有时候,显而易见的解决方案更简单、更好。
待办事项:
<span>@Title</span>

@code {
    [Parameter] // add this parameter to accept title 
    public string Title { get; set; }
}

页面:

<input @bind="_newTodo"/>
<button @onclick="@AddTodoItem">+</button>

<ol>
    @foreach (var todoItem in _todoItems)
    {
        <li>
            <TodoItem Title="@todoItem.Title"/>
        </li>
    }
</ol>

@code {
    private readonly IList<TodoItem> _todoItems = new List<TodoItem>();
    private string _newTodo;

    private void AddTodoItem()
    {
        if (!string.IsNullOrWhiteSpace(_newTodo))
        {
            _todoItems.Add(new TodoItem { Title = _newTodo });
            _newTodo = string.Empty;
        }
    }
}

输出:
在此输入图像描述


每个组件都有两个实例吗?当你创建一个新的TodoItem时,这会创建一个实例,然后在TodoItem上进行循环会在页面上创建另一个副本,唯一的区别是它从现有的实例中传递参数进来。 - nh43de

0

当然可以使用foreach来渲染列表。这篇文章解释得很好。

这里有一个例子。请注意在点击事件中使用item,这样您就知道点击了哪个项目。需要使用lambda表达式完成此操作。

<section data-info="List of images">
@foreach (var item in this.Parent.CurrentCard.Images.OrderByDescending(a => a.InsertedDate))
{
    <div class="border border-secondary m-2">
        <img class="img-fluid" src="/api/image/fetch/@item.StorageName" alt="@item. Filename">

        <div class="card-body">
            <h5 class="card-title">Card title</h5>
            <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
            <a href="#" @onclick="()=> RemoveImage(item)" class="btn btn-secondary">Remove</a>
        </div>
    </div>
}

0

我刚刚建立了一个帮助系统,其中包含一个LinkButton组件,我是这样渲染它的:

 foreach (HelpCategory category in Categories)
 {
     <LinkButton Category=category Parent=this></LinkButton>
     <br />
 }

每个HelpCategory都有一个或多个可展开的帮助文章。
这是我的LinkButton代码,它做了更多相同的事情:
@using DataJuggler.UltimateHelper.Core
@using ObjectLibrary.BusinessObjects

@if (HasCategory)
{
    <button class="linkbutton" 
    @onclick="SelectCategory">@Category.Name</button>

    @if (Selected)
    {
        <div class="categorydetail">
            @Category.Description
        </div>
        <br />
        <div class="margintop">
            @if (ListHelper.HasOneOrMoreItems(Category.HelpArticles))
            {
                foreach (HelpArticle article in Category.HelpArticles)
                {
                    <ArticleViewer HelpArticle=article Parent=this> 
                    </ArticleViewer>
                    <br />
                    <div class="smallline"></div>
                }
            }
        </div>
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接