【问题标题】:Generated table with rowspan causing extra cells生成的表格与行跨度导致额外的单元格
【发布时间】:2012-11-12 12:15:18
【问题描述】:

HTML

<table id="tableAppointment" bgcolor="#fcfcfc" border="1" cellspacing="1" width="100%">
 <thead>
  <tr>
   <td class="csstextheader" width="70px"></td>
   <td class="csstextheader" width="70px"><b>Time Slot&nbsp;</b></td>
   <td><b>Room 7</b></td>
   <td><b>Room 8</b></td>
   <td><b>Room 9</b></td>
   <td><b>Room 10</b></td>
  </tr>
 </thead>
 <tbody>
  <tr class="csstablelisttd">
   <td width="70px">08:00AM</td>
   <td>00</td>
   <td class="csstdred">John</td>
   <td>&nbsp;</td>
   <td>&nbsp;</td>
   <td>&nbsp;</td>
  </tr>
 </table> 

C#

private void GenerateTable() {
    for(int i = 0; i < tableAppointment.Rows.Count; i++) {
        foreach(DataRow dr in dataTableAcqModality.Rows) {
            cell = new HtmlTableCell() {
                InnerHtml = "&nbsp;"
            };
            cell.Style.Add("word-wrap", "break-word");
            cell.Attributes.Remove("class");
            cell.Attributes.Remove("rowspan");
            cell.Style.Remove("display");

            tableAppointment.Rows[i].Cells.Add(cell);
            tableAppointment.Style.Add("table-layout", "fixed");

            if(i == 0) {
                cell.Attributes.Add("ID", RoomID.ToString());
                cell.InnerHtml = String.Format(
                    "<span id='{0}'>{1}</span>",
                    RoomID, Roomname
                );
                tableAppointment.Rows[0].Attributes.Add("class", "csstextheader");
            }
        }
    }
}

protected void Page_Load(object sender, EventArgs e) {
    for(int i = 0; i < tableAppointment.Rows.Count; i++) {
        for(int j = 0; j < tableAppointment.Rows[i].Cells.Count; j++) {
            // This is where I need to remove the extra cells added 
            // after providing rowspan :(
        }
    }
}

this JSBin 中,您可以看到由于rowspan 被添加到上面行中的单元格而卡在我的行右侧的额外单元格。我试图弄清楚如何删除这些。任何建议表示赞赏!

【问题讨论】:

  • 您确实应该正确缩进您的 html 代码。现在,我认为没有人会阅读它。这同样适用于下面的 C# 代码。虽然这是可读的,因为它很短,但正确的缩进仍然是一件好事。
  • 你能解释一下你想删除哪个单元格吗?无法理解标准
  • 在 jsbin 中查看我添加了额外的单元格,因此必须将其删除..
  • 如何生成表格?我认为最好不要添加那些额外的单元格,然后在创建后尝试删除它们。另外,你的表不是服务器控制的,如何在后面的代码中访问它?
  • 向我们展示您是如何生成表格的?那么我们也许可以帮助您完全不生成这些额外的单元格,然后您就不必删除它们。

标签: c# jquery asp.net .net html


【解决方案1】:

为您简化它..

如果您在单元格中使用[rowspan="2"] --> 那么您必须从下一行中删除一个单元格

例子:

<table id="Table1" >
    <tr>
        <td rowspan="2" style="border-style:solid"></td>
        <td style="border-style:solid"></td>
    </tr>
    <tr>
        <td style="border-style:solid"></td>          
    </tr>
</table>

如果您在单元格中使用 [ rowspan="3" ] --> 那么您必须从接下来的 两行 行中删除一个单元格

例子:

<table id="Table1" >
    <tr>
        <td rowspan="3" style="border-style:solid"></td>
        <td style="border-style:solid"></td>
    </tr>
    <tr>
        <td style="border-style:solid"></td>          
    </tr>
    <tr>
        <td style="border-style:solid"></td>          
    </tr>
</table>

【讨论】:

    【解决方案2】:

    由于缺少代码,我不得不做出假设:获取数据、数据是什么样子、约会如何添加到表中。

    我做了两件事来解决这个问题。 1 - 我切换了循环的顺序,而不是循环遍历每个房间一段时间,而是循环遍历一个房间的所有时间跨度,然后再移动到下一个房间。 2 - 由于更改 #1,我能够将时间跨度计数器增加需要删除的单元格数量(不推荐)

    默认.aspx.cs

    public partial class _Default : Page
    {
      //Used to store generated data.
      List<Room> Rooms = new List<Room>();
    
      protected void Page_Load(object sender, EventArgs e)
      {
        if (!IsPostBack)
        {
          //To simulate the datasource
          GenerateData();
    
          //Generate the output
          GenerateTable();
        }
      }
    
      private void GenerateData()
      {
        //Generate Rooms
        foreach (var roomNumber in Enumerable.Range(7, 4))
        {
          var newRoom = new Room();
    
          newRoom.RoomID = roomNumber;
          newRoom.Roomname = "Room " + roomNumber.ToString();
          //Generate 40 15-minute time slot appointments for each room
          for (var count = 0; count < 40; ++count)
          {
            var newAppointment = new Appointment();
    
            newAppointment.Id = (roomNumber * 40) + count;
            newAppointment.Name = " ";
            newAppointment.NumberOfTimeSlots = 1;
    
            newRoom.Appointments.Add(newAppointment);
          }
    
          Rooms.Add(newRoom);
        }
    
        Rooms[0].Appointments[0].Name = "John";
        Rooms[0].Appointments[0].NumberOfTimeSlots = 1;
    
        Rooms[0].Appointments[2].Name = "John";
        Rooms[0].Appointments[2].NumberOfTimeSlots = 3;
    
        Rooms[1].Appointments[14].Name = "calc";
        Rooms[1].Appointments[14].NumberOfTimeSlots = 3;
    
        //More can be added
      }
    
      private void GenerateTable()
      {
        //Moved outside of the loop since it is globally setting the table and does not need to run for each row.
        tableAppointment.Style.Add("table-layout", "fixed");
    
        /**********************************************************************************************
         * Major change 1:
         * I flipped the order of the loops, I changed it from row->column to column->row.
         * What this allows you to do is skip the step of adding additional rows for the current room
         * by increment the row counter (not a good practice, need to refactor code).
         **********************************************************************************************/
    
        //You had: foreach(DataRow dr in dataTableAcqModality.Rows) {
        //I am assuming that this is a list of rooms to display
        foreach (var dr in Rooms)      
        {
    
          for (int i = 0; i < tableAppointment.Rows.Count; ++i)
          {
            var cell = new HtmlTableCell();
    
            cell.Style.Add("word-wrap", "break-word");
            cell.Attributes.Remove("class");
            cell.Attributes.Remove("rowspan");
            cell.Style.Remove("display");
    
            tableAppointment.Rows[i].Cells.Add(cell);
    
            if (i == 0) //Indicating the header row
            {
              cell.Attributes.Add("ID", dr.RoomID.ToString());
              cell.InnerHtml = String.Format(
                  "<span id='{0}'>{1}</span>",
                  dr.RoomID, dr.Roomname
              );
              tableAppointment.Rows[0].Attributes.Add("class", "csstextheader");
            }
            else
            {
    
              /***********************************************************************
               * Assumption that this is how you are adding the appointments to the 
               * table, did not see it in your quesiton
               ***********************************************************************/ 
              //i-1 to offset the header row
              cell.InnerHtml = dr.Appointments[i-1].Name;
    
              //NumberOfTimeSlots does not have to be part of the object, you are already doing it one way (not shown)
              cell.RowSpan = dr.Appointments[i - 1].NumberOfTimeSlots;
    
              //This is the inportant part, incrementing the row counter for this table by the number of cells you need to be removed becasue of the rowspan.
              //NOTE: I do not like the idea of messing with a loop counter, I would try to refactor your code, but since it was not provided this is a temporary fix.
              i += dr.Appointments[i - 1].NumberOfTimeSlots - 1;
            }
          }
        }
      }
    }
    
    public class Room
    {
      public int RoomID { get; set; }
      public string Roomname { get; set; }
      public List<Appointment> Appointments { get; set; }
    
      public Room()
      {
        Appointments = new List<Appointment>();
      }
    }
    
    public class Appointment
    {
      public int Id { get; set; }
      public string Name { get; set; }
      public int NumberOfTimeSlots { get; set; }
    }
    

    默认.aspx:

    时隙 08:00AM00 15 30 40

        <tr><td>09:00AM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>10:00AM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>11:00AM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>12:00PM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>01:00PM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>02:00PM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>03:00PM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>04:00PM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
    
        <tr><td>05:00PM</td><td>00</td></tr>
        <tr><td>&nbsp;</td><td>15</td></tr>
        <tr><td>&nbsp;</td><td>30</td></tr>
        <tr><td>&nbsp;</td><td>40</td></tr>
      </tbody>
    </table>
    

    【讨论】:

      【解决方案3】:

      即使我不知道您想要什么,也不知道为什么,I wrote some jQuery 删除多余的列,因为这就是我们在 StackOverflow 上所做的。

      我不保证此代码的效率或实际有用性。

      $(document).ready(function() {
        $('table tr').each(function(i, v) {
          var cols = $(this).find('td');
          $(this).find('td[rowspan]').each(function() {
            var idx = $(this).index();
            console.log(idx);
            for(var j = 1; j < $(this).prop('rowspan'); j++) {
              $('table tr').eq(i+j).find('td').eq(idx).hide();
            }
          });
        });
      });
      

      编辑:显然你只需要给行一个高度来避免相互折叠的行为:

      tr { height: 30px; }
      

      编辑 2:我确实更新了我的 jQuery 以隐藏具有行跨度的单元格正下方的单元格。在您的示例中,您似乎有冲突的约会。开个玩笑,您可能希望确保没有调度冲突,并且首先不要编写那些额外的单元格。

      提前处理此问题的一般策略是将与表格大小相同的多维布尔数组(例如cellsUsed)初始化为 false,然后在打印具有行跨度的单元格时,标记行跨度- 1 个数组位置为真。然后,当需要编写一个对应于设置为 true 的数组索引的单元格时,您只需 输出任何内容。如果碰巧在您标记为不输出的单元格中定义了实际约会,那么您将遇到完全不同的问题,并且必须处理它。

      编辑:这里演示了为什么您必须隐藏多余的单元格或遍历表格两次以删除它们以避免错误:

      这是一个示例表,其中“a”是行跨度 > 1 的单元格。“x”指定需要删除的额外单元格,“-”表示应为空白的空白。

      这是表格中的起始数据:

      a-a-
      x-xa
      xaxx
      -x-x
      

      如果您从左下角到右上角开始删除,就会发生这种情况。删除倒数第二行中连接到约会的额外单元格后,最后一行中只有三个单元格。因此,当您从下一个约会向下遍历以删除该行中的第四个单元格时,您会收到错误。

      a-a-
      x-xa
      xaxx
      --x!
      

      如果您尝试从右上角到左下角删除,当您删除第二个约会时,您最终会错误地删除另一个约会(两个“a”相邻堆叠)。

      a-a-
      -xa
      axx
      -x-x
      

      避免在生成表格后删除单元格出现问题的唯一方法是标记要删除的所有单元格,然后从右到左删除每一行中的单元格。

      【讨论】:

      • 但它没有看到像块...看到当我们将行跨度给单元格时它看起来像一个块...在我的 jsbin 中给行跨度后的单元格看起来像一个块..当我们给行跨度要单元格其下面的行单元格必须删除才能看到像一个块............
      • 这里,这个版本有一个可怕的视觉伪影。
      • 在上面的 jsbin 中,你看到人的约会是固定的时间和房间号,如果行跨度是 3,那么每个时间段是 15 分钟,那么如果行跨度是 2,那么人的约会时间是 45 分钟,那么人的约会时间是 30 分钟,如果行跨度为 1,则人员预约时间为 15 分钟..所以当我给行跨度时,它下面的单元格会添加到表中..这是我的场景..那么我们如何删除额外添加的单元格..
      • @Nikhil 我几乎明白你在说什么。
      • @Nikhil 我已经解释过了。 Ricky @ 1:45 Room 8 与 Feder @ 1:15 Room 8 冲突。您无法真正正确地显示重叠的表格单元格。
      【解决方案4】:

      试试这样的

      protected void Page_Load(object sender, EventArgs e)
      {
          for(int i = 0; i < tableAppointment.Rows.Count; i++)
          {
              for(int j = 0; j < tableAppointment.Rows[i].Cells.Count; j++)
              {
                   // Assuming you have set the rowSpan by now.
                   // TODO: Handle the possibility of missing rowspan attribute.
                   int rowSpan = int.Parse(tableAppointment.Rows[i].Cells[j].Attributes["rowspan"]);
                   if (rowSpan > 0) {
                      // Now try to look ahead for rows and remove their j'th cell.
                      for (int k = j+1; k < j + rowSpan; k++)
                      {
                         tableAppointment.Rows[k].Cells.RemoveAt(j);
                         // TODO: Validate if k is not beyond available rows. It shoudn't be if rowspans are correct.
                      }
                   }
              }        //Here i have to remove those extra cell added after giving rowspan       
          }
      }
      

      注意:此代码未经测试,甚至未经编译。提供更多作为指导。

      话虽如此,我相信您可以在生成表格时更好地处理这个问题。如果我理解正确(可能是我没有理解)你已经静态创建了表,然后你注入了约会。 这就是为什么你会患上这种细胞外综合症。如果您动态生成整个表格,这不应该发生在您身上。

      【讨论】:

        【解决方案5】:

        如果您的单元格是空白的,那么您可以隐藏 css。喜欢;

        table{empty-cells:hide;}    
        

        【讨论】:

        • 这会隐藏他表格中的大部分单元格。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-23
        • 1970-01-01
        • 1970-01-01
        • 2014-05-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多