.Net Core 5.0 .cshtml Razor Pages "if" 阻止打开 HTML 标签而不关闭它

.Net Core 5.0 .cshtml Razor Pages "if" Block Open HTML Tag Without Closing It

我不确定我是否有足够的词汇来正确地问这个问题,我希望这个问题的标题措辞正确......无论哪种方式,我都试图在 table使用 .Net Core 5.0 (Visual Studio 16.10.0) 的 .cshtml Razor 页面。我正在使用 Entity Framework Core 5.0.11,但我不确定这是否与此相关。

我正在从数据库中提取数据,我想做的是构建一个包含两列的 table。所以,我希望我拉的第一个项目在第一列,我拉的第二个项目在第二列,我拉的第三个项目在第一列(现在在第一个项目下面),第四个项目我拉到第二列(现在在第 2 项下)等等。

我正在尝试生成包含任意数量项目的两列 table。

(编辑:对不起,如果这个 table 看起来一团糟。当我在编辑页面时,它看起来像我想要的,但是当我在最后一页上查看我的问题时它看起来就像原始文本。只是想说明我知道这一点,但不知道该怎么做。或者,也许这只是我的屏幕,它在你的屏幕上看起来很棒。祈祷吧。)

像这样: |Header(但忽略实际代码中的headers)|另一个Header(它只是说这里需要一个header行)| |--------------------------------------------|--- ----------| |项目 1|项目 2| |项目 3|项目 4|

现在,这是我正在尝试使用的代码,但它似乎不起作用:

@if (Model.MyListOfItems is not null) // I can verify that it is not null
{
<table>
    <tbody>
        @{ int count = 0; }
        @foreach (var item in Model.MyListOfItems)
        {
            count++;
            @if (count % 2 == 1)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(i => item.Text)
                    </td>
            }
            else
            {
                    <td>
                        @Html.DisplayFor(i => item.Text)
                    </td>
                </tr>
            }
        }
        @if (count % 2 == 1)
        {
            </tr>
        }
    </tbody>
</table>
}

现在,你可以看到我在做什么,对吧?对于奇数项目,打开一个新的 table 行。对于偶数项,关闭它。如果我们以奇数项结束,我们将打开一行,以便最后的 if 语句将其关闭。这样,我们得到一个 table 就像我上面描述的那样。

但是,这不起作用。它不会编译。我在文件的第一行收到类似 ; expected 的错误。它开始抱怨此代码之前的代码。我开始收到一堆 such and such doesn't exist in this current context

但问题是...我知道其余的代码都很好,因为如果我将其更改为这个

@if (Model.MyListOfItems is not null) // I can verify that it is not null
{
<table>
    <tbody>
        @{ int count = 0; }
        @foreach (var item in Model.MyListOfItems)
        {
            count++;
            @if (count % 2 == 1)
            {
                <tr>
                    <td>
                        @Html.DisplayFor(i => item.Text)
                    </td>
                </tr> <!-- Added this -->
            }
            else
            {
                <tr> <!-- Added this -->
                    <td>
                        @Html.DisplayFor(i => item.Text)
                    </td>
                </tr>
            }
        }
        @if (count % 2 == 1)
        {
            <!-- </tr> --> <!-- Removed This -->
        }
    </tbody>
</table>
}

然后它就可以正常工作并编译了。 table 显然看起来不像我想要的样子,但我把它包括在内是为了说明我知道这不是我的代码的问题,甚至是我的其余代码,不是编译器的问题在开头的 if 语句中看到 <tr> 标记的末尾,然后没有将 } else { 识别为 C# 代码(因此整个页面都在抛出错误)。

我知道编译器正试图将我从我自己中拯救出来,但如果我可以强制它编译我......至少相当有信心 table 将正确形成 HTML.即使不是,如果我可以编译它,那么我可以看到 table 这段代码 确实 产生了什么样的 table 并从那里修复它。但是,编译器显然不喜欢我在 if 块中打开一个标签然后不关闭它。

我之前 运行 遇到过与此类似的问题,这也是为什么我确信它是编译器而不是我的原因,但通常我只是找到其他方法来做到这一点。而且我确定这次我会这样做,我会在发送此邮件后立即开始尝试,但我想我还是会和大家核实一下;我想一定有我遗漏的东西。

此外,是的,我尝试将 else 更改为 @else,但这并没有解决问题,只是开始抛出错误,指出那里不允许 @else

所以,我认为,要问我想问的问题还有很长的路要走,但我认为所有的阐述都是必要的。无论如何,我想问题是:

当我在该块中打开 HTML 标记但不关闭 HTML 标记时,如何强制编译器将右括号识别为代码?

(编辑:根据@Dai 的回复向 table 添加了明确的 <tbody>

好吧,如果有人知道我的问题的答案,我仍然会非常感激,因为就像我提到的,我以前 运行 遇到过类似的问题,并且总是必须找到解决方法。但是,如果有人想知道,这是我的解决方法。

我正在使用 Bootstrap 框架,它有这个专栏组织。每页 12 列,每个容器内还有 12 列。基本上,您可以将页面分成越来越小的 12 组。这不是最好的解释,但是...这是他们的网页 https://getbootstrap.com/docs/4.0/layout/grid/

无论如何,我没有使用 table,而是使用网格系统,如下所示:

<div class="row">
@if (Model.MyListOfItems is not null) // I can verify that it is not null
    {
        int count = 0;
        @foreach (var item in Model.MyListOfItems)
        {
            count++;
            <div class="col-6">
                @Html.DisplayFor(i => item.Text)
            </div>
            @if (count % 2 == 0)
            {
                <br />
            }
        }
        @if (count % 2 ==0)
        {
            <br />
        }
    }
</div>

我知道最后两个 if (count % 2 == 0) 块可能根本不需要,因为 Bootstrap 的网格系统是响应式的,但我只是喜欢明确。不过,为了每个人的理智,这应该会产生相同的结果:

<div class="row">
@if (Model.MyListOfItems is not null) // I can verify that it is not null
    {
        @foreach (var item in Model.MyListOfItems)
        {
            <div class="col-6">
                @Html.DisplayFor(i => item.Text)
            </div>
        }
    }
</div>

您可以对项目列表进行分块,以便您可以像这样遍历子列表列表:

<table>
    <tbody>
    @{
        var listOfSubLists = Model.MyListOfItems
                                .Select((x, i) => new { Index = i, Value = x })
                                .GroupBy(x => x.Index / 2)
                                .Select(x => x.Select(v => v.Value).ToList())
                                .ToList();
    }
    @foreach (var subList in listOfSubLists)
    {
        <tr>
            @foreach (var item in subList)
            {
                <td>
                    @Html.DisplayFor(i => item.Text)
                </td>
            }
        </tr>
    }
    </tbody>
</table>

这样,就可以使用<table>标签了。我认为这比在 UI.

中使用 Bootstrap col- class 创建 table 更合适

还有 .NET6 LINQ will support a built-in chunk method 允许您将列表分块到一行代码中:

var listOfSubLists = Model.MyListOfItems.Chunk(2);