2012-08-05 69 views
2

寻找帮助我tripple嵌套中继器逻辑问题。ASP.Net嵌套中继器逻辑地狱

背景
我建立了预订房间和资源从SQL Server数据库中提取数据的时间表系统。

表结构

Table 1 - tblrooms 
room_id (INT) PK 
room_name (varchar(50)) 
room_resource (INT) 

Table 2 - tblperiods 
period_id (INT) PK 
period_time_start (DATETIME) 
period_time_end (DATETIME) 
period_name (nvarchar(50)) 

Table 3 - tblbookings 
booking_id (INT) PK 
period_id (INT) 
room_id (INT) 
booking_status (INT) 
booking_date (DATETIME) 
booking_subject (nvarchar(50)) 

问题 我已经大部分得到了中继器拉出来的数据作为然而只需要第一列是不断填充,我真的很努力工作,如何将预订数据提取出来并根据需要制定时间表。 (请参阅什么,我已经得到了工作附截图)

ASPX页面代码

<asp:Repeater ID="drPeriods" runat="server" OnItemDataBound="drPeriods_OnItemDataBound"> 

     <HeaderTemplate> 
     <table class="table table-striped table-bordered table-condensed"> 
      <tr> 
       <th style="width:16.66%"><asp:Label ID="lblResourceHeader" runat="server" /></th> 
     </HeaderTemplate> 

     <ItemTemplate> 

       <th style="width:16.66%"><asp:Label ID="lblPeriod" runat="server" Text='<%# Eval("period_name") %>' /> - <asp:Label ID="lblPeriodStart" runat="server" Text='<%# Eval("period_time_start") %>' /> to <asp:Label ID="lblPeriodEnd" runat="server" Text='<%# Eval("period_time_end") %>' /></th> 

     </ItemTemplate> 

     <FooterTemplate> 
      </tr> 

      <asp:Repeater ID="drResources" runat="server" OnItemDataBound="drResources_OnItemDataBound"> 

        <ItemTemplate> 

        <tr> 
         <td height="50"> 
          <asp:Label ID="lblResource" runat="server" Text='<%# Eval("room_name") %>' /> 
          <br /><asp:Label ID="lblResourceDetails" runat="server" /> 
         </td> 
         <asp:Label ID="lblFreeBooking" runat="server" Visible="false" /> 

         <asp:Repeater ID="drBookings" runat="server" OnItemDataBound="drBookings_OnItemDataBound"> 

          <ItemTemplate> 

           <td height="50"> 
            <asp:Label ID="lblCellContent" runat="server" /> 
           </td> 

          </ItemTemplate> 

         </asp:Repeater> 

        </tr> 

        </ItemTemplate> 

       </asp:Repeater> 

      </table> 

     </FooterTemplate> 

    </asp:Repeater> 

代码隐藏

Namespace Staff 

Public Class Rb 
    Inherits System.Web.UI.Page 
    Private _periodId As Integer 


    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

     If Not IsPostBack Then 

      txtDate.Text = Request.QueryString("d") 

      'check for weekend dates, show message if it is. 
      Dim iWeekday As Integer = Weekday(Request.QueryString("d")) 

      If iWeekday = 1 Or iWeekday = 7 Then 

       lblMsg.Text = "<div class='alert alert-info alert-block'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;It's the weekend.</h4><p>The date you have choosen is a weekend, resources cannot be booked on weekends.</p></div>" 
       lblMsg.Visible = True 
       drPeriods.Visible = False 

      Else 

       Dim objConnection As SqlConnection 
       Dim objCommand As SqlCommand 
       Dim objDataReader As SqlDataReader 

       objConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OPSDConnectionString").ConnectionString) 

       'Get Periods 
       objCommand = New SqlCommand("SELECT period_id, CONVERT(char(5), period_time_start, 108) AS period_time_start, CONVERT(char(5), period_time_end, 108) AS period_time_end, period_name FROM tblrb_periods", objConnection) 

       Try 
        objConnection.Open() 
        objDataReader = objCommand.ExecuteReader() 

        If objDataReader.HasRows Then 

         drPeriods.DataSource = objDataReader 
         drPeriods.DataBind() 
         objDataReader.Close() 

        Else 

         drPeriods.Visible = False 
         lblMsg.Text = "<div class='alert alert-error alert-block'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;Error!</h4><p>Periods have not yet been setup, please set these up by selecting the periods tab above, if you cannot see this tab please ask the helpdesk administrator to set these up for you.</p></div>" 
         lblMsg.Visible = True 
         objDataReader.Close() 

        End If 

       Catch ex As Exception 

        'Inform of the error 
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex) 

       Finally 
        objCommand.Dispose() 
        objConnection.Close() 
        objConnection.Dispose() 

       End Try 

      End If 

     End If 

    End Sub 

    Protected Sub drPeriods_OnItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles drPeriods.ItemDataBound 

     If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then 

      _periodId = e.Item.DataItem("period_id") 

     End If 

     If e.Item.ItemType = ListItemType.Header Then 

      Dim lblResourceHeader As Label = drPeriods.Controls(0).Controls(0).FindControl("lblResourceHeader") 
      Dim layoutView As Integer = Request.QueryString("v") 
      Select Case layoutView 
       Case 1 ' Rooms 
        lblResourceHeader.Text = "Rooms" 
       Case 2 ' Resources 
        lblResourceHeader.Text = "Resources" 
       Case 3 ' Both 
        lblResourceHeader.Text = "Rooms &amp; Resources" 
       Case Else 
        lblResourceHeader.Text = "Rooms &amp; Resources" 
      End Select 

     End If 

     If e.Item.ItemType = ListItemType.Footer Then 

      Dim objConnection As SqlConnection 
      Dim objCommand As SqlCommand 
      Dim objDataReader As SqlDataReader 

      'find repeater in the footer of drPeriods (repeater) 
      Dim drResources As Repeater = drPeriods.Controls(drPeriods.Controls.Count - 1).Controls(0).FindControl("drResources") 
      Dim layoutView As Integer = Request.QueryString("v") 

      'Get Rooms 
      objConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OPSDConnectionString").ConnectionString) 

      Select Case layoutView 
       Case 1 ' Rooms 
        objCommand = New SqlCommand("SELECT * FROM tblrb_rooms WHERE room_resource = 1 ORDER BY room_name", objConnection) 
       Case 2 ' Resources 
        objCommand = New SqlCommand("SELECT * FROM tblrb_rooms WHERE room_resource = 2 ORDER BY room_name", objConnection) 
       Case 3 ' Both 
        objCommand = New SqlCommand("SELECT * FROM tblrb_rooms ORDER BY room_name", objConnection) 
       Case Else 
        objCommand = New SqlCommand("SELECT * FROM tblrb_rooms ORDER BY room_name", objConnection) 
      End Select 

      Try 
       objConnection.Open() 
       objDataReader = objCommand.ExecuteReader() 

       drResources.DataSource = objDataReader 
       drResources.DataBind() 
       objDataReader.Close() 

      Catch ex As Exception 

       'Inform of the error 
       Elmah.ErrorSignal.FromCurrentContext().Raise(ex) 

      Finally 
       objCommand.Dispose() 
       objConnection.Close() 
       objConnection.Dispose() 

      End Try 

     End If 

    End Sub 

    Protected Sub drResources_OnItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) 

     If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then 

      Dim lblResourceDetails As Label = e.Item.FindControl("lblResourceDetails") 
      If e.Item.DataItem("room_resource") <> 2 Then 
       lblResourceDetails.Text = "[ <a href='#' class='withajaxpopover' title='Room Details' data-load='resourceManagerViewDetails.aspx?id=" & e.Item.DataItem("room_id") & "'>View Room Details</a> ]" 
      End If 

      Dim objConnection As SqlConnection 
      Dim objCommand As SqlCommand 
      Dim objDataReader As SqlDataReader 
      Dim drBookings As Repeater = e.Item.FindControl("drBookings") 
      Dim lblFreeBooking As Label = e.Item.FindControl("lblFreeBooking") 

      'Get Bookings 
      objConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OPSDConnectionString").ConnectionString) 
      objCommand = New SqlCommand("SELECT tblrb_bookings.booking_status, tblrb_bookings.booking_subject, tblrb_bookings.booking_notes FROM tblrb_bookings WHERE (tblrb_bookings.room_id = @room_id) AND (tblrb_bookings.booking_date = @booking_date) AND (tblrb_bookings.period_id = @period_id)", objConnection) 

      objCommand.Parameters.Add("@room_id", SqlDbType.Int, 10).Value = e.Item.DataItem("room_id") 
      objCommand.Parameters.Add("@period_id", SqlDbType.Int, 10).Value = _periodId 
      objCommand.Parameters.Add("@booking_date", SqlDbType.DateTime).Value = Request.QueryString("d") 

      Try 
       objConnection.Open() 
       objDataReader = objCommand.ExecuteReader() 

       If objDataReader.HasRows Then 

        drBookings.DataSource = objDataReader 
        drBookings.DataBind() 
        objDataReader.Close() 

       Else 

        'free period 
        lblFreeBooking.Text = "<td height='50'><div class='alert alert-block alert-success'><h4 class='alert-heading'><i class='icon-ok'></i>&nbsp;Free.</h4><p><a href='#'>Click here to book this resource.</a></p></div></td>" 
        lblFreeBooking.Visible = True 

       End If 

      Catch ex As Exception 

       'Inform of the error 
       Elmah.ErrorSignal.FromCurrentContext().Raise(ex) 

      Finally 
       objCommand.Dispose() 
       objConnection.Close() 
       objConnection.Dispose() 

      End Try 

     End If 

    End Sub 

    Protected Sub drBookings_OnItemDataBound(sender As Object, e As System.Web.UI.WebControls.RepeaterItemEventArgs) 

     Dim lblCellContent As Label = e.Item.FindControl("lblCellContent") 

     Select Case e.Item.DataItem("booking_status") 
      Case 1 
       'timetabled 
       lblCellContent.Text = "<div class='alert alert-block alert-error'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;Timetabled.</h4><p>" & e.Item.DataItem("booking_subject") & "</p></div>" 

      Case 2 
       'user booked 
       lblCellContent.Text = "<div class='alert alert-block'><h4 class='alert-heading'><i class='icon-warning-sign'></i>&nbsp;Booked.</h4><p>" & e.Item.DataItem("booking_subject") & ".</p></div>" 

     End Select 

    End Sub 


    Protected Sub btnDateSelect_Click(sender As Object, e As System.EventArgs) Handles btnDateSelect.Click 

     'quick reload of page 
     Response.Redirect("resourceManager.aspx?v=" & Request.QueryString("v") & "&d=" & txtDate.Text) 

    End Sub 

End Class End Namespace 

谁能与我如何能得到帮助所需的布局,以便当建立时间表时,房间和时段包含他们的每个小区的正确预订数据相应的栏目。

预先感谢您可以提供任何指针,已经花了3天的时候我可以用新鲜的一双眼睛:-)

问候做,

奥兹

Repeater Data Issue

回答

3

首先,我认为你过度复杂化你的控制方式。如果您要使用LINQ或EF来访问数据库,您可以使用2个嵌套中继器完成此任务,并且不需要复杂的代码。但是,您可以通过下调简化查询,像这样开始:

SELECT * 
FROM tblperiods p 
    CROSS JOIN tblrooms r 
    LEFT JOIN tblbookings b ON p.period_id = b.period_id AND r.room_id = b.room_id AND b.booking_date = '2012-08-01' 

这将让你足够的信息来产生一个查询整个输出给定的一天。如果你不想使用EF或LINQ-to-SQL,你仍然可以做一些LINQ的魔术来将它们分离出来,然后你可以使用它来进行数据绑定(原谅C#,VB.NET是有点生锈!):

DataTable dt = new DataTable(); 
dt.Fill(objDataReader);   // Loads all data into the DataTable 
var groupedRows = dt.Rows.Cast<DataRow>().GroupBy(row => new { RoomId = (int) row["room_id"], RoomName = (string) row["room_name"] }); 
rpRows.DataSource = groupedRows; 
rpRows.DataBind(); 

然后,你将有中继器,像这样:

<table> 
<thead><tr><th>Rooms &amp; Resources</th> 
<asp:Repeater runat="server" id="rpHeader"> 
    <ItemTemplate> 
     <td><%# Eval("period_name") %></td> 
    </ItemTemplate> 
</asp:Repeater> 
</tr></thead> 
<asp:Repeater runat="server" id="rpRows"> 
    <ItemTemplate> 
     <tr> 
      <th><!-- Put room header stuff here --><%# Eval("Key.RoomName") %></th> 
      <asp:Repeater runat="server" DataSource="<%# Container.DataItem %>"> 
       <ItemTemplate> 
        <td> 
         <!-- Per-booking info --> 
         <asp:Label runat="server" Visible='<%# Eval("booking_id") == DBNull.Value %>'>Not Booked</asp:label> 
         <asp:Label runat="server" Visible='<%# Eval("booking_id") != DBNull.Value %>'>Booked!</asp:label> 
        </td> 
       </ItemTemplate> 
      </asp:Repeater> 
     </tr> 
    </ItemTemplate> 
</asp:Repeater> 
</table> 

我没有给予代码数据绑定标题行,但是这仅仅是一个select * from tbl_periods

注意,无的代码已经过测试,并且可能需要对数据绑定进行一些调整。

+0

感谢SQL从未想过在一次快速命中中将其拉出。转储到数据表中也很有意义。所以为了得到期间头文件,我仍然需要3个嵌套中继器是否正确?已经添加了上面的建议,但在运行时,我得到一个错误,room_name不存在查看数据我看到列标题不存在如何引用room_name的位置在数据表中,在这种情况下5? – OPSL 2012-08-05 19:48:07

+0

现在得到了房间名称,我的错误没有注意:-)有更多的游戏与您的建议,并会letyou知道我如何继续下去。 – OPSL 2012-08-05 20:42:49

+0

你需要第三个中继器,但它不会嵌套。我已经通过回答修改以显示它会去的地方。至于RoomName,其意图是从分组的Key属性中访问它 - 这是GroupBy进入后的.Select(new {...})位的地方 – Richard 2012-08-05 20:42:57

0

跳到我身上的一件事是这条线......

Dim drResources As Repeater = drPeriods.Controls(drPeriods.Controls.Count - 1).Controls(0).FindControl("drResources") 

尝试的东西代替它像

Dim drResources As Repeater = e.Item.FindControl("drResources") 

(语法也许有点过 - 我的VB是片状的:)

我还删除try catch只有基本原则工作 - 这也许是一个错误正在产生,但你从来没有看到它。

+0

这两个版本都正常工作我测试了这些extensivley,这个问题围绕屏幕截图中的第一列(P1 - 09:00到10:00),预订应该在最后一列,它与所有其他数据一样正在被忽略。 我不知道是否有三个嵌套中继器是最好的方式去与此? – OPSL 2012-08-05 18:10:49