【问题标题】:C# For each loop in a a table?C# 对于表中的每个循环?
【发布时间】:2016-10-05 13:28:46
【问题描述】:

我试图在 for each 循环的帮助下显示各种信息。 我为每个循环创建了一个循环,它遍历项目列表。在此列表中还有另一个项目列表。

目前显示如下:

我的代码是:

@foreach (Invoice invoice in ViewBag.Invoices)
{
    <table>
        <tr>
            <th>Customer</th>
            <th>Product</th>
            <th>Quantity</th>
            <th>Price</th>
            <th>Total Price</th>
        </tr>

        @foreach (OrderItem orderItem in invoice.OrderItems)
        {
        <tr>
            <td>@invoice.Customer.Firstname @invoice.Customer.Lastname</td>
            <td>@orderItem.Product.Title </td>
            <td>@orderItem.Quantity </td>
            <td>@orderItem.Product.Price </td>            
            <td>@orderItem.TotalPrice</td>
        </tr>
        }

        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td class="border-top">@invoice.TotalPrice</td>
        </tr>
    </table>
}

但是,我不希望它显示两次客户姓名。而且我不想让客户独自一人。因此,我尝试将起始标签与客户一起放在 foreach 循环之外,而不是用 &lt;tr&gt; 标签结束 foreach 循环。所以它看起来像这样:

@foreach (Invoice invoice in ViewBag.Invoices)
{
    <table>
        <tr>
            <th>Customer</th>
            <th>Product</th>
            <th>Quantity</th>
            <th>Price</th>
            <th>Total Price</th>
        </tr>

        <tr>
        <td>@invoice.Customer.Firstname @invoice.Customer.Lastname</td>

        @foreach (OrderItem orderItem in invoice.OrderItems)
        {
            <td>@orderItem.Product.Title </td>
            <td>@orderItem.Quantity </td>
            <td>@orderItem.Product.Price </td>            
            <td>@orderItem.TotalPrice</td>
        </tr>
        <tr>
        }


            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td class="border-top">@invoice.TotalPrice</td>
        </tr>
    </table>
}

更新的解决方案

我遵循@Ed Plunkett 的明智的话并将本地字符串初始化为null。我创建了一个 if/else 语句来检查是否设置了前一个客户,并在循环结束时初始化了前一个客户的值。

@{string prevCust = null; }

@foreach (Invoice invoice in ViewBag.Invoices)
{
    <table>
        <tr>
            <th>Customer</th>
            <th>Product</th>
            <th>Quantity</th>
            <th>Price</th>
            <th>Total Price</th>
        </tr>

        @foreach (OrderItem orderItem in invoice.OrderItems)
        {
            <tr>
            @if (prevCust != invoice.Customer.Firstname + invoice.Customer.Lastname)
            {
                <td>@invoice.Customer.Firstname @invoice.Customer.Lastname</td>
            }
            else
            {
                <td></td>
            }

            <td>@orderItem.Product.Title </td>
            <td>@orderItem.Quantity </td>
            <td>@orderItem.Product.Price </td>
            <td>@orderItem.TotalPrice</td>
        </tr>

            prevCust = invoice.Customer.Firstname + invoice.Customer.Lastname;
        }

        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td class="border-top">@invoice.TotalPrice</td>
        </tr>
    </table>
}

【问题讨论】:

  • 在 之前占用那个“}”字符?
  • 您打开行 (&lt;tr&gt;) 一次并关闭行 (&lt;/tr&gt;) 零次或多次 次。无论 Razor 是否聪明到知道你正在这样做,都不要那样做,因为你的 HTML 会被破坏。只需创建一个局部变量StringprevCustomerName,初始化为null,并在循环块的end处更新它。在循环块的开头,如果新客户名称与prevCustomerName 相同,则不要将其插入该行的 HTML 中。
  • 顺便说一句,您在第三个 之后忘记了一个
  • 当您的收藏不包含任何元素时会发生什么?在这种情况下,输出为&lt;tr&gt;&lt;tr&gt;,这是无效的。
  • 对不起,我在代码中放了太多 ,我现在按我的意思编辑它。

标签: c# asp.net-mvc foreach


【解决方案1】:

我会做穴居人风格:只需创建一个局部变量String prevCustomerName,初始化为 null,然后在循环块的末尾更新它。在循环块的开头,如果新客户名称与prevCustomerName 相同,则不要将其插入该行的 HTML 中。

我喜欢你在内部循环中使用&lt;/tr&gt;\n&lt;tr&gt; 的原始代码,但我花了一分钟才弄清楚你在做什么,Razor 似乎完全困惑了。而且您仍然需要使用特殊情况将其丑化,以便在非第一行上添加一个空单元格。如果无论哪种方式,您都无法输入if,请做穴居人。

【讨论】:

    【解决方案2】:

    在表格中使用迭代时,尽可能保持表格的结构和简单是有帮助的(即使对您自己,而不仅仅是对于剃刀或您使用的任何视图引擎)。

    (您问题上的 cmets 应该足以解释为什么这是一个好主意)

    尝试在每张发票上使用多个 tr 来实现您的目标。例如:

    @foreach (Invoice invoice in ViewBag.Invoices)
    {
        <table>
            <tr>
                <th>Customer</th>
                <th>Product</th>
                <th>Quantity</th>
                <th>Price</th>
                <th>Total Price</th>
            </tr>
    
            <tr>
              <td colspan="4">@invoice.Customer.Firstname @invoice.Customer.Lastname</td>
            </tr>
    
            @foreach (OrderItem orderItem in invoice.OrderItems)
            {
                <tr>
                  <td>@orderItem.Product.Title </td>
                  <td>@orderItem.Quantity      </td>
                  <td>@orderItem.Product.Price </td>            
                  <td>@orderItem.TotalPrice    </td>
                </tr>
            }
    
            <tr>
                <td colspan="4"></td>
                <td class="border-top">@invoice.TotalPrice</td>
            </tr>
        </table>
    }
    

    如果这有助于简化您的工作,您甚至可以求助于为每张发票生成一张表格。

    【讨论】:

    • 这绝对有效,但我不希望客户显示在自己的行上。我希望它与产品显示在同一行。使用您的代码(我添加了一个额外的空 以将信息推送到一列)它将导致:puu.sh/ryz8M/3bebb239f5.png 在此示例中为清楚起见,我添加了一个边框。
    【解决方案3】:

    如果不是 ASP 专家,我想你必须以不同的方式处理第一行:

    <tr>
      <td>@invoice.Customer.Firstname @invoice.Customer.Lastname</td>
      <td>@orderItem.Product.Title </td>
      <td>@orderItem.Quantity      </td>
      <td>@orderItem.Product.Price </td>            
      <td>@orderItem.TotalPrice    </td>
    </tr>
    

    现在处理循环中的其余部分,省略第一个(已处理的)元素:

    @foreach (OrderItem orderItem in invoice.OrderItems.Skip(1))
    {
        <tr>
          <td/>
          <td>@orderItem.Product.Title </td>
          <td>@orderItem.Quantity      </td>
          <td>@orderItem.Product.Price </td>            
          <td>@orderItem.TotalPrice    </td>
        </tr>
    }
    

    更通用的方法是使用带有索引的for-loop 并检查您是否正在处理第一个元素:

    @for(int i = 0; invoice.OrderItems.Count; i++)
    {
        <tr>
          <td>@(i != 0 ? invoice.Customer.Firstname + " " + invoice.Customer.Lastname : "")</td>
          <td>@invoice.OrderItems[i].Product.Title </td>
          <td>@invoice.OrderItems[i].Quantity      </td>
          <td>@invoice.OrderItems[i].Product.Price </td>            
          <td>@invoice.OrderItems[i].TotalPrice    </td>
        </tr>
    }
    

    但是我不确定这是否是有效的 ASP 语法。

    【讨论】:

    • 它会起作用,但这不是 DRY。你做了两次同样的事情,在你的另一个例子中,你对每次迭代都进行了不必要的检查。
    • 您的三元运算符在第二个示例中不是有效的剃须刀代码。
    • 我想你会选择@(i != 0 ? invoice.Customer.Firstname + " " + invoice.Customer.Lastname : "")
    • @TimothyGroote 感谢您的支持,我对 JSP 更熟悉了。
    • 天差地别吧? :)
    猜你喜欢
    • 2019-01-24
    • 1970-01-01
    • 2013-07-19
    • 2014-06-17
    • 2020-04-06
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多