【问题标题】:Accessing listview itemtemplate from codebehind从代码隐藏访问列表视图项模板
【发布时间】:2011-09-02 17:11:59
【问题描述】:

我希望动态更改 ListView 的 ItemTemplate 中的列数:

<asp:ListView runat="server" ID="ReportListView" DataSourceID="ReportListViewSDS">
 <LayoutTemplate>
   <table>
       <tr>
           <asp:PlaceHolder runat="server" ID="itemPlaceHolder" />
       </tr>
   </table>
 </LayoutTemplate>
 <ItemTemplate>
       <!-- need to dynamically create the number of columns in the code behind 
            based on the select statement in the SelectCommand -->
 </ItemTemplate>
</asp:ListView>

然后在后面的代码中我得到了:

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

    ' Based on The Request.Form variables sent, the SQL command will 
    ' select x number of columns:
    ' SqlStatement = "SELECT " for each Request.Form values " FROM staff"
    '      example: "SELECT Fname, Lname, email, phone FROM staff"
    ' Run sql command.

    ' that all works, the question now is how do i change the ItemTemplate 
    ' so that it has the correct number of columns.  Something like this: (pseudo code)
    For each row found in sql command
       ReportListView.ItemTemplate.Add( "<tr>" )
       For each Request.Form as i
            ReportLIstView.ItemTemplate.Add( "<td>" & sqlresult(i) & "</td>" )
       Next
       ReportListView.ItemTemplate.Add( "</tr>" )
    Next
 End Sub

也许还有另一种方法可以解决,但这是迄今为止唯一的想法。 asp.net新手,任何建议,非常欢迎!谢谢!

【问题讨论】:

    标签: asp.net vb.net listview itemtemplate


    【解决方案1】:

    我认为您将不得不采取一些不同的做法。试试这样的:

    <table>
        <asp:ListView ID="ListView1" runat="server">
            <ItemTemplate>
                <tr>
                   <asp:PlaceHolder Id="PlaceHolder1" runat="server" />
                </tr>
            </ItemTemplate>
        </asp:ListView>
    </table>
    

    语法可能并不完美,但请尝试在您的代码中执行以下操作:

    For Each listItem As ListViewDataItem In ListView1.Items
        Dim plc As PlaceHolder = DirectCast(listItem.FindControl("PlaceHolder1"), PlaceHolder)
        If plc IsNot Nothing Then
            For Each item As String In Request.Form
                plc.Controls.Add(New Literal(String.Format("<td>{0}</td>", item)))
            Next
        End If
    Next
    

    【讨论】:

    • 好主意,已实现,但在此出现错误:plc.Controls.Add(New Literal(String.Format("{0}", item)) )。错误是“public sub new() 的参数太多”。不熟悉 Literal,以及它在这里的使用方式,有什么建议吗?
    • 仅供参考:因为 plc.Controls.Add 需要和对象我试过这个: Dim tb As New TableCell() tb.Text = "Hello" plc.Controls.Add( tb) 这不会给出任何错误,但它不会出现“Hello”被添加到列表视图的每一行。 :(
    • 我得到了这个工作。必须在 for each 循环之前添加 ListView.DataBind() 。现在的问题是 Request.Form 中的 For Each Item As String,我实际上需要它遍历从 sql 返回的每一列,因为我会将 sql 命令的返回值放在 plc.Control 中。有什么想法吗?谢谢!
    • 这其实就是使用ItemDataBound事件的重点。每次 listView 绑定一行数据时,都会使用包含要绑定的数据行的事件参数触发此事件。因此,您可以将另一个答案与这个答案结合起来,并同时拥有列标题和从每一行检索到的值。
    【解决方案2】:

    另一种方法是以相同的方式设置 ItemTemplate,但由于您使用的是数据绑定控件,因此您可能希望利用列表视图的 DataBound 事件。这种语法可能并不完美,因为您可能正在使用不同的集合来绑定到列表(这将在查询执行后完成),但这应该会让您走上正轨:

    Protected Sub ReportListView_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ReportListView.ItemDataBound
        If (e.Item.ItemType = ListViewItemType.DataItem) Then
            Dim di As Data.DataRowView = e.Item.DataItem
            Dim plc As PlaceHolder = DirectCast(e.Item.FindControl("PlaceHolder1"), PlaceHolder)
    
            For Each c In di.Row.ItemArray
                Dim l As New Literal
                l.Text = String.Format("<td>{0}</td>", c.ToString)
                plc.Controls.Add(l)
            Next
    
        End If
    End Sub
    

    我通常会在此类工作中使用中继器,因为它是准系统且轻量级的。你真的没有利用我所看到的任何列表视图功能。

    【讨论】:

    • 代码看起来很棒,实现了。出现错误:“对象引用未设置为对象的实例。”参考这一行:plc.Controls.Add(l)。玩了一下,asp.net 似乎无法意识到 'l' 不是空对象。非常感谢您的帮助。
    • 顺便说一句,我使用列表视图是因为我希望能够对列表进行排序,而且我不熟悉中继器。我会调查的,谢谢!
    • 我对代码进行了编辑...抱歉。在 FindControl 行中应该是:e.Item.FindControl 而不是 ListViewItem.FindControl
    【解决方案3】:

    结合我收到的答案,这就是我要做的:

    <asp:ListView runat="server" ID="ReportListView" DataSourceID="ReportListViewSDS">
     <ItemTemplate>
       <table>
           <tr>
               <asp:PlaceHolder runat="server" ID="itemPlaceHolder" />
           </tr>
       </table>
     </ItemTemplate>
    </asp:ListView>
    

    代码背后:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
     ' Based on The Request.Form variables sent, the SQL command will 
     ' select x number of columns:
     ' SqlStatement = "SELECT " for each Request.Form values " FROM staff"
     '      example: "SELECT Fname, Lname, email, phone FROM staff"
     ' Run sql command.
    
     ' this seems to actually run the sql, and bind the results.  If i don't run the function DataBind(), it's as if the sql never runs.
     ReportListView.DataBind() 
    
     ' the rest of the work is done in the next function.
    End Sub
    
    Protected Sub ReportListView_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ListViewItemEventArgs) Handles ReportListView.ItemDataBound
    
        If (e.Item.ItemType = ListViewItemType.DataItem) Then
            Dim plc As PlaceHolder = DirectCast(e.Item.FindControl("itemPlaceHolder"), PlaceHolder)
            Dim di As Data.DataRowView = e.Item.DataItem()
    
            For Each c In di.Row.ItemArray
                Dim l As New Literal
                l.Text = String.Format("<td class='customreport'>{0}</td>", c.ToString)
                plc.Controls.Add(l)
            Next
    
        End If
    End Sub
    

    非常感谢其他 2 个答案的方向,这肯定让我 90%,只是其他几个调整,我很高兴。谢谢!

    【讨论】:

      【解决方案4】:

      我使用此代码隐藏项目模板中的元素

      visible='<%# Eval("Abstract").ToString().Length == 0 ? false : true %>' 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-31
        相关资源
        最近更新 更多