动态创建的标签和文本框无法定位

Dynamically created Labels and TextBoxes are unable to be positioned

我正在构建一个动态创建的弹出窗口 window,其中包含一个动态创建的网格和控件(标签和文本框)。 网格部分工作正常,不是问题。但是,控件给我带来了问题。 这个想法是为网格中的每一列创建一个 Label 和一个 TextBox。我能够很好地创建它们,但根本无法定位它们。 label.Locationlabel.Toplabel.point 等。return 一个错误,表明它不是 Label 的一部分。 TextBox 也会发生同样的事情。 当它们显示时,它们出现在水平行中,TextBoxLabel 重叠,除非宽度设置得足够大(当然会留下一堆空的 space)。 我希望在 Label 之后立即与 TextBox 垂直对齐。 就像是: 标签文本:文本框

正在将这些控件添加到 asp:Panel (pnlFields)

For Each col As DataColumn In dataTable.Columns
      Dim label As New Label()
      label.Text = col.ColumnName & ": "
      label.Height = 24
      label.Width = label.Text.Length()
      pnlFields.Controls.Add(label)
      Dim textBox As New TextBox()
      textBox.Height = 24
      textBox.Width = 100
      pnlFields.Controls.Add(textBox)
Next

我想尝试让 Label 宽度与其包含的文本一样长而不是静态的,这样我(希望)能够将 TextBox 位置设置为在 Label.

之后

无论如何,我似乎根本无法指定位置来执行此操作。 有什么想法吗?

谢谢!

编辑:标记

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <asp:Panel runat="server" ID="pnlFields" CssClass="FormStyle" Height="600px" />  
      <asp:Panel runat="server" ID="pnlFinder" CssClass="FormStyle">
       <telerik:RadGrid ID="batchRecords" runat="server" Skin="Windows7" ShowHeader="true" AutoGenerateColumns="true" Width="600px" AutoPostBack="true">
           <MasterTableView CommandItemDisplay="Bottom" AllowPaging="true">
               <CommandItemSettings ShowAddNewRecordButton="false" />
               <Columns>
                   <telerik:GridButtonColumn UniqueName="selectRecord" HeaderText="Edit" CommandName="Select" Text="Edit Record" ButtonType="ImageButton" ImageUrl="~/images/icons/pencil.png">
                   </telerik:GridButtonColumn>
               </Columns>
           </MasterTableView>
       </telerik:RadGrid>
   </asp:Panel>
</asp:Content>

我真的,但真的不认为有必要创建这些文本框。有大量内置的重复控件。如果你即时创建这些控件,那么你就不能连接事件背后的代码 - 所以你完全放弃了使用 asp.net 和所有这些伟大的内置控件的全部原因。

我看不出您为什么可以注入和包含一些额外的“div”并将样式应用于这些 div。但是,在你走那条路之前?

您应该尝试提出一个非常有力的理由,说明您为什么要走这条路,而不是使用列表视图、网格视图或转发器控件。它们专为一遍又一遍地重复数据而设计 - 使用非常少的代码和非常少的标记来实现。

填写这些控件的数据来自哪里?或者甚至相反 - 控件的结果将放置在哪里?你看,通过使用中继器或其他什么?它们是数据绑定的。所以,一个人可以说添加 2 行或 15 行数据,然后在一次 sql 更新操作中你可以写出所有这些数据! - 换句话说,您正在重复一些控制 - 但这里的大问题是基于什么以及如何?

如前所述,如果您创建并注入此类控件,则您无法为这些控件设置或连接事件。因此,对于这里的最终目标,请认真思考。您可能会修复布局问题,但是您的下一个 issue/problem 将是事件代码,然后是获取该输入并以某种方式将其推回某个数据库所需的复杂代码。结果真的不推荐这条路

此外,使用其中一个内置的“重复”对象可以让您相对轻松地在屏幕上编辑该数据,并且如前所述,写回一行或 15 行数据可以通过相同的代码 - 并且比尝试将动态控件注入该表单更容易。此外,您将使用什么“id”来引用这些控件,以及一旦您设法注入这些控件?

这里的最终目标是关键概念。

我发现 gridview 很好 - 通常标记较少。但是,当您开始在该网格中说出 3 个或更多自定义控件时?然后我喜欢 listview 而不是 gridview(因为 listview 允许您拖放和使用标准 asp.net 控件,而不必将该控件放在模板块中。但是,你的情况?每行只有两个额外的控件网格?当然,坚持使用网格视图。

那么,要将这两个额外的列添加到该网格吗?你可以这样做:

首先,我将使用向导来创建这个网格视图。然后我取消了数据源 ID 设置,还删除了表单上的数据源控件。

所以,我数不到 1 分钟 - 放下 gridview。单击表单中的配置数据源。这个:

所以我配置了数据源,生成了 gv,然后删除了数据源 ID 并从标记中删除了数据源控件。所以,这需要 30 秒的时间,我最终得到了这个网格:

所以,我们得到这个:

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
            <Columns>
                <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
                <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
                <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
            </Columns>
        </asp:GridView>

加载这个网格的代码是这样的:

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

    If IsPostBack = False Then

        LoadGrid()

    End If

End Sub

Sub LoadGrid()

    Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
                New SqlConnection(My.Settings.TEST3))

        cmdSQL.Connection.Open()
        GridView1.DataSource = cmdSQL.ExecuteReader
        GridView1.DataBind()

    End Using
End Sub

现在我们有了这个:

好的,不错,用更少的时间写了这个 post!!!

请注意我们最多只需要 3 行代码来加载网格?

超级简单。

好的,现在让我们在网格中添加一个标签和一个文本框。

好吧,只需对 gv 模板执行此操作即可:

因此,请注意我们是如何添加两个额外的列的。标记是这样的:

      <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
            <Columns>
                <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
                <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
                <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />

                <asp:TemplateField HeaderText = "My label">
                    <ItemTemplate>
                        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>

                <asp:TemplateField HeaderText = "My Text Box">
                    <ItemTemplate>
                        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    </ItemTemplate>
                </asp:TemplateField>

            </Columns>
        </asp:GridView>

现在,当我们 运行 以上内容时,我们得到:

我的意思是那很容易还是什么?我可以将那个标签 + 文本框放在 SAME TEMPLATE 列中。因此,您可以非常自由地将那些额外的列添加到该网格中,而且我们不必编写代码——事实上这非常简单,结果是我们现在有了额外的两列——并且可以非常轻松地实现这一点。

而且我们还可以相对轻松地 set/change 标签和文本框的值 - 甚至基于该行的其他列数据,并且可以非常轻松地再次这样做。

所以,在一天结束的时候?当我们有上面概述的这种好方法时,我不建议您尝试手动添加两列。甚至更好的是,用户在每一行和文本框中键入的值都可以通过代码从该 gv 中提取和引用 - 并且可以轻松地完成 2 行或 20 行数据。

编辑: 由于 gv 的控制和添加将在 运行 时间(动态),那么您仍然想使用 gv 对象模型 - 反对该模型是一个非常糟糕的主意 - 顺其自然。

因此,您可以通过这种方式向 gv 添加额外的绑定字段列:

子 LoadGrid()

    Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
                New SqlConnection(My.Settings.TEST3))

        cmdSQL.Connection.Open()
        GridView1.DataSource = cmdSQL.ExecuteReader
        AddColumns()

        GridView1.DataBind()

    End Using
End Sub

Sub AddColumns()

    Dim lblfield As New BoundField()
    lblfield.HeaderText = "Label1"
    GridView1.Columns.Add(lblfield)

    Dim txtfield As New BoundField()
    txtfield.HeaderText = "TextBox"
    GridView1.Columns.Add(txtfield)


End Sub

然后在项目绑定事件上,您还可以像这样注入您选择的控件:

 Protected Sub GridView1_RowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then

        Dim MyLabel As New Label
        MyLabel.ID = "Label1"
        MyLabel.Text = "Label Text"
        e.Row.Cells(5).Controls.Add(MyLabel)

        Dim MyTextBox As New TextBox
        MyTextBox.ID = "Textbox1"
        MyTextBox.Text = "Text box value"
        e.Row.Cells(6).Controls.Add(MyTextBox)

    End If

End Sub

所以,现在有了这个简单的标记:

       <link href="Content/cuscosky.css" rel="stylesheet" />
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ID">
            <Columns>
                <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" />
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
                <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
                <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />

            </Columns>
        </asp:GridView>

那么,上面的代码呢?我们得到相同的结果,这个输出:

编辑: 我通过在标记中创建 HTML Table 解决了这个问题,然后以编程方式添加带有控件(标签和文本框)和唯一 ID 的行和单元格。然后我能够找到并使用正确的数据填充这些控件。 比尝试手动定位每个控件更容易。

我能够解决定位控件的问题。 我需要使用 label.Style.Add() 并输入所需的值。 它现在似乎工作正常。

谢谢!