65.9K
CodeProject 正在变化。 阅读更多。
Home

动态将控件加载到 DataGrid 中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.14/5 (20投票s)

2004年9月22日

3分钟阅读

viewsIcon

158782

downloadIcon

2450

一种在运行时向 DataGrid 加载控件,然后允许 DataSet 更新的方法。

Sample Image - showing the concept in action!

引言

ASP.NET 的 DataGrid 是一个强大的控件,它支持嵌入文本框、按钮、下拉列表等控件…… 这种控件的强大是以复杂性为代价的。 最近,我需要生成一个屏幕,其中包含将由应用程序用户在运行时填充的数据。 数据的显示格式可能会根据用户输入而改变。 保存的数据可能来自列表的选择、True/False 条件或文本字符串。 这是一个关于数据可能如何被查看的例子。

乍一看,DataGrid 控件非常适合显示此数据。 DataGrid 将接受嵌入控件,但是,设计和嵌入最容易在 Visual Studio 中完成。 我的要求是允许用户配置数据,并动态填充屏幕。 另外一个 "可有可无" 的功能是允许通过单个按钮更新屏幕上的任何数据字段。

第 1 步 – 审查数据

为了本文的目的,我将使用 XML 文件作为持久数据存储。 这里使用的示例是一个序列化的 DataSet,包含两个表,第一个表 – 命名为 MyDetails,包含这些重要的元素

<myDetails>
    <name>Name</name>
    <value>Mark</value>
    <type>txtbox</type>
    <populate>NameSource</populate>
</myDetails>
  • Name: 正在存储的数据元素的名称;
  • Value: 元素的存储值;
  • Type: 用于呈现数据的控件;和
  • Populate: 用于填充 DropDownList 的辅助表(当 type=ddl 时)。

此示例将支持 Textbox ('txtbox')、CheckBox ('checkbox') 和 DropDownList ('ddl') 控件。 在此示例中,第二个表 – 命名为 CarMake – 填充了名为汽车制造商的 DropDownList。 下面提供了该表的一个示例

<CarMake>
    <carmake>Ford</carmake>
</CarMake>

第 2 步 – 将 DataGrid 插入到 ASPX 屏幕上

在我的例子中,我将显示两列,第一列将保存元素名称,第二列将保存实例值。 此时,我们将使网格为空。 在其他情况下,您可能希望在设计时使用与数据无关的控件填充屏幕。

<asp:datagrid BorderWidth="1" id="dg1" 
     style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 8px" 
     runat="server" AutoGenerateColumns="False" ShowHeader="False" 
     BorderStyle="None" GridLines="Both">
  <Columns>
    <asp:TemplateColumn>
      <ItemTemplate>
      </ItemTemplate>
      </asp:TemplateColumn>
      <asp:TemplateColumn>
      <ItemTemplate>
      </ItemTemplate>
    </asp:TemplateColumn>
  </Columns>
</asp:datagrid>

第 3 步 – 将数据绑定到 DataGrid

绑定控件很重要,即使我们在控件中没有任何数据元素,也要为 DataSet 的每一行引发绑定事件。

        dg1.DataSource = myDS
        dg1.DataMember = "myDetails"
        DataBind()

第 4 步 - 将控件插入到 DataGrid 中

动态插入控件的技巧是使用与屏幕上 DataGrid 控件关联的 ItemDataBound 事件。 ItemDataBound 事件将为 DataSet 中的每一行数据调用。 每次引发行事件时,都会创建相应的控件并将其插入到 DataGrid 中。 此示例使用 e.Item.DataSetIndexDataGrid 行和 DataSource 行链接起来。

Private Sub dg1_ItemDataBound(ByVal sender As Object, _
     ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) _
     Handles dg1.ItemDataBound

     'ensure we are looking at an item being bound
     If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = _
                                 ListItemType.AlternatingItem Then
        'always insert the dataelement name into the first column as a label.
        Dim myLBL As New Label
        myLBL.EnableViewState = True
        myLBL.Text = dgTable(dg1).Rows(e.Item.DataSetIndex)(0)
        e.Item.Cells(0).Controls.Add(myLBL)

        If dgTable(dg1).Rows(e.Item.DataSetIndex)(2) = "txtbox" Then
        'insert textbox and load with data
            Dim myTB As New TextBox
            If Not IsPostBack Then
                myTB.Text = dgTable(dg1).Rows(e.Item.DataSetIndex)(1)
            End If
            e.Item.Cells(1).Controls.Add(myTB)
        End If
        If dgTable(dg1).Rows(e.Item.DataSetIndex)(2) = "checkbox" Then
        'insert checkbox and load with data
            Dim myCB As New CheckBox
            If Not IsPostBack Then
                If dgTable(dg1).Rows(e.Item.DataSetIndex)(1).tolower = "t" Then
                    myCB.Checked = True
                Else
                    myCB.Checked = False
                End If
            End If
            e.Item.Cells(1).Controls.Add(myCB)
        End If
        If dgTable(dg1).Rows(e.Item.DataSetIndex)(2) = "ddl" Then
        'insert dropdownlist and load with data
            Dim myDDL As New DropDownList
            'for simplicity I will assume the ‘CarMake’ table 
            'always as the dropdownlist data source 

            For yy As Int16 = 0 To _
                      dg1.DataSource.Tables("CarMake").Rows.Count - 1
                myDDL.Items.Add(dg1.DataSource.Tables("CarMake").Rows(yy)(0))
            Next
            e.Item.Cells(1).Controls.Add(myDDL)

            If Not IsPostBack Then
                myDDL.SelectedIndex = _
                  CType(dgTable(dg1).Rows(e.Item.DataSetIndex)(1), Int16)
            End If
        End If
    End If
End Sub

'This function returns the table bound to the datagrid
Private Function dgTable(ByVal dg As DataGrid) As DataTable
    Return dg1.DataSource.tables(dg1.DataMember)
End Function

第 5 步 – 允许全屏,单击按钮更新

最后,我们准备将更新后的数据传回给 DataSet。 此示例在 prerender 事件上执行更新。 要更新,我们将逐行分析 DataGrid 并相应地更新 DataSet

Private Sub dg1_PreRender(ByVal sender As Object, _
         ByVal e As System.EventArgs) Handles dg1.PreRender
    ' this is where the dataset update actually happens!!
    Dim y As Int16
    'run through each line in the datagrid
    For y = 0 To dgTable(dg1).Rows.Count - 1
        'repopulate the dataset with content based on the embedded control
        If dg1.Items(y).Cells(1).Controls(0).GetType Is GetType(DropDownList) Then
            Dim myIndex As Int32 = _
              CType(dg1.Items(y).Cells(1).Controls(0), DropDownList).SelectedIndex
            dgTable(dg1).Rows(y)(1) = myIndex.ToString
        End If
        If dg1.Items(y).Cells(1).Controls(0).GetType Is GetType(TextBox) Then
            Dim myStr As String = _
                CType(dg1.Items(y).Cells(1).Controls(0), TextBox).Text
            dgTable(dg1).Rows(y)(1) = myStr
        End If
    Next
    dg1.DataSource.WriteXml(strFileLoc)
End Sub

结论

此示例使用了 XML 文件,并提供了仅插入三个控件的选项。 一个更完整的示例可以提供具有特定验证的控件(例如,电话号码或纯字符串)。

此示例未处理屏幕上控件引发的事件。 这将是未来提交的主题。

祝你好运,编码愉快!!

© . All rights reserved.