简体   繁体   English

有没有办法使用变量来控制 VB.NET 中代码隐藏页面的 html 标记的 ID?

[英]Is there a way to use variables to control the ID of html tags for a code-behind page in VB.NET?

I'm making a simple form.我正在制作一个简单的表格。 I have Default.aspx, Default.aspx.vb, and Default.aspx.designer.vb.我有 Default.aspx、Default.aspx.vb 和 Default.aspx.designer.vb。
Default.aspx.vb contains a Public jsonItems As List(Of JsonItem) , where a JsonItem is just an object with a few strings defined, like Id , Label , and Type . Default.aspx.vb 包含一个Public jsonItems As List(Of JsonItem) ,其中JsonItem只是一个定义了一些字符串的对象,例如IdLabelType This is generated by Page_Load , which reads a Json file to tell the page the form's contents.这是由Page_Load生成的,它读取一个 Json 文件来告诉页面表单的内容。

Then, Default.aspx contains:然后,Default.aspx 包含:

    <ul>
      <%For Each item In jsonItems%>
      <li>
        ...
        <ol>
          <asp:TextBox ID="<%=item.Label%>" runat="server"></asp:TextBox>
        </ol>
      </li>
      <%Next%>
    </ul>

This, however, doesn't work as I would expect it to.然而,这并没有像我期望的那样工作。 I believe this is because the Designer page wants to know exactly what form elements will be on the page... It autogenerates Protected WithEvents <%=item.label%> As ... in the designer page, and complains that it isn't a valid name.我相信这是因为设计器页面想确切地知道页面上的表单元素......它在设计器页面中自动生成Protected WithEvents <%=item.label%> As ... ,并抱怨它不是t 有效名称。

Is there a way to do what I'm trying to do?有没有办法做我想做的事? Should I be building the entire form in the.. code-behind ( Default.aspx.vb ) instead of what I'm doing now?我应该在.. 代码隐藏( Default.aspx.vb )中构建整个表单,而不是我现在正在做的事情吗?

For the record, I'm used to working in React, which is why I initially took this direction (I wrote it first in JS and I was adapting it to VB).作为记录,我习惯于在 React 中工作,这就是我最初选择这个方向的原因(我首先用 JS 编写它,然后将它改编为 VB)。

Injection of asp.net controls into a page does not tend to work very well at all.将 asp.net 控件注入到页面中往往效果不佳。

You can inject HTML, but then again , you now writing your own code anyway, and again that not a huge help.您可以注入 HTML,但话又说回来,您现在无论如何都要编写自己的代码,而且这并没有太大的帮助。

As a general approach?作为一般方法?

Should I be building the entire form in the.. code-behind我应该在.. 代码隐藏中构建整个表单吗

No, you don't want to write that much code.不,你不想写那么多代码。 You lay out the markup with the designer - code behind is to pull data say to fill out those existing controls.您与设计器一起布置标记 - 后面的代码是提取数据来填写那些现有的控件。

I mean, you have to define that markup some place.我的意思是,您必须在某个地方定义该标记。 But with web forms, the general idea is that you drop in the controls you want.但是对于 web 表单,一般的想法是你放入你想要的控件。

Of course, there is a boat load of controls, and many are data aware.当然,有大量的控件,而且许多控件都具有数据意识。 So, the trick, the idea, the goal?那么,诀窍,想法,目标?

Well, with so many control choices, it often hard to pick a control.好吧,有这么多控件选择,通常很难选择控件。

So, for a table like layout, then GridView.所以,对于像布局这样的表格,然后是 GridView。 For fancy table layout, then ListView.对于花哨的表格布局,然后是 ListView。

For repeating records - say like a "card view", then datalist works well.对于重复记录 - 比如说“卡片视图”,那么 datalist 效果很好。

so in webforms land?所以在网络表单领域? You tend to layout the markup with the desinger.您倾向于使用设计器来布局标记。

Then you use code behind to fill out the data, or whatever.然后你使用后面的代码来填写数据,或者其他什么。

So, say I drop in a Gridview, like this:所以,假设我放入一个 Gridview,如下所示:

    <asp:GridView ID="GHotels" runat="server" AutoGenerateColumns="False" 
            DataKeyNames="ID" CssClass="table">
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName" HeaderText="LastName"    />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName"  />
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:CheckBox ID="chkActive" runat="server" Checked='<%# Eval("Active") %>' />
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Hotel Information" ItemStyle-HorizontalAlign="Center">
                    <ItemTemplate>
                        <asp:Button ID="cmdView" runat="server" Text="Info" CssClass="btn" 
                            OnClick="cmdView_Click" />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

I did use the wizard to help me create the GV.我确实使用向导来帮助我创建 GV。 (but then I removed the sql datasource that was created on the page). (但后来我删除了在页面上创建的 sql 数据源)。

So, now my code to say load up the grid would be this:所以,现在我说加载网格的代码是这样的:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    If Not IsPostBack Then
        LoadGrid
    End If
End Sub

Sub LoadGrid()

    Dim rstData As DataTable
    rstData = MyRst("SELECT * FROM tblHotelsA ORDER BY HotelName")
    GHotels.DataSource = rstData
    GHotels.DataBind()

End Sub

Public Function MyRst(strSQL As String) As DataTable
    Dim rstData As New DataTable
    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand(strSQL, conn)
            conn.Open()
            rstData.Load(cmdSQL.ExecuteReader)
            rstData.TableName = strSQL
        End Using
    End Using
    Return rstData
End Function

And I get this:我明白了:

在此处输入图像描述

Note how I did set the GV to CssClass="table".请注意我是如何将 GV 设置为 CssClass="table" 的。 (that is the boot strap class - so you get a nice looking gird). (那是引导带类 - 所以你会得到一个漂亮的束带)。

And I have a button - edit that row.我有一个按钮 - 编辑该行。

Again, just a plain jane button click for that row.同样,只需单击该行的简单按钮即可。

So, right below the Grid, I could drop in a div, and some controls to display/edit that one row.因此,在网格正下方,我可以放入一个 div 和一些控件来显示/编辑该行。

Say, like this:说,像这样:

    <div id="HotelInfo" runat="server" 
        style="float:left;display: none;border:solid;padding:15px;background-color:white;width:48%"
        clientidmode="Static" >
        <style>
            .iForm label {display:inline-block;width:120px}
            .iForm input {border-radius:8px;border-width:1px;margin-bottom:10px}                
            .iForm textarea {border-radius:8px;border-width:1px;margin-bottom:10px}     
            .iForm input[type=checkbox] {margin-right:4px}
        </style>

        <div style="float:left" class="iForm">
                <label>HotelName</label><asp:TextBox ID="txtHotel" runat="server"  width="280"></asp:TextBox> <br />
                <label>First Name</label><asp:TextBox ID="txtFirst" runat="server"  width="280"></asp:TextBox> <br />
                <label>Last Name</label><asp:TextBox ID="txtLast" runat="server"  width="280"></asp:TextBox> <br />

                <label>City</label><asp:TextBox ID="tCity" runat="server"  Width="140"></asp:TextBox> <br />
                <label>Province</label><asp:TextBox ID="tProvince" runat="server"  Width="75"></asp:TextBox> <br />
        </div>
        <div style="float:left;margin-left:20px" class="iForm">
            <label>Description</label> <br />
            <asp:TextBox ID="txtNotes" runat="server" Width="450" TextMode="MultiLine" 
                Height="150px"  ></asp:TextBox> <br />
            <asp:CheckBox ID="chkActive" Text=" Active" runat="server" TextAlign="Right" />
            <asp:CheckBox ID="chkBalcony"  Text=" Has Balcony" runat="server" TextAlign="Right" />
            <asp:CheckBox ID="chkSmoking" Text="Smoking Rooms" runat="server" TextAlign="Right" />
        </div>

        <div style="clear:both">
            <asp:Button ID="cmdSave" runat="server" Text="Save" CssClass="btn" />
            <asp:Button ID="cmdCancel" runat="server" Text="Cancel" CssClass="btn"
                style="margin-left:20px" OnClientClick="$('#HotelInfo').dialog('close');return false;"
                />
            <asp:Button ID="cmdDelete" runat="server" Text="Delete" CssClass="btn"
                style="margin-left:40px"
                />
        </div>
    </div>

And, since we all have jQuery installed, I added jquery.UI.而且,由于我们都安装了 jQuery,我添加了 jquery.UI。

So right after above, I have this:所以在上面之后,我有这个:

    <script>
        function popinfo(pbtn, strHotelName) {

            // btn = row buttion - we use that for position of pop
            btn = $(pbtn)
            myDialog = $("#HotelInfo")
            myDialog.dialog({
                title: strHotelName,
                modal: true,
                position: { my: "left top", at: "right bottom", of: btn },
                width: "48%",
                appendTo: 'form'
            })
        }
    </script>

So, now our row click event:所以,现在我们的行点击事件:

Protected Sub cmdView_Click(sender As Object, e As EventArgs)

    ' Row click - get hotel informaton, fill out the pop div
    Dim btn As Button = sender
    Dim gRow As GridViewRow = btn.NamingContainer

    Dim intPK As Integer = GHotels.DataKeys(gRow.RowIndex).Item("ID")
    Dim rstData As DataTable = MyRst("SELECT * FROM tblHotelsA WHERE ID = " & intPK)


    Call EditOne(rstData, btn)


End Sub

Sub EditOne(rstData As DataTable, btn As Button)

    With rstData.Rows(0)
        txtHotel.Text = .Item("HotelName").ToString
        txtFirst.Text = .Item("FirstName").ToString
        txtLast.Text = .Item("LastName").ToString
        tCity.Text = .Item("City").ToString
        tProvince.Text = .Item("Province").ToString
        chkActive.Checked = .Item("Active")
        chkBalcony.Checked = .Item("Balcony")
        chkSmoking.Checked = .Item("Smoking")
        txtNotes.Text = .Item("Description").ToString
    End With

    ' ok, div information filled out, now call our js pop function.
    Dim strHotelName = """Edit Information for " & rstData.Rows(0).Item("HotelName") & """"
    Dim strJavaScript As String = "popinfo(" & btn.ClientID & "," & strHotelName & ");"

    ViewState("rstData") = rstData
    Page.ClientScript.RegisterStartupScript(Me.GetType(), "My Pop script", strJavaScript, True)


End Sub

So, now we see/get this when we click on a row button:所以,现在我们在单击行按钮时看到/得到这个:

在此处输入图像描述

the save button in above, say this code:上面的保存按钮,说这段代码:

Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click

    Dim rstData As DataTable = ViewState("rstData")

    With rstData.Rows(0)
        .Item("HotelName") = txtHotel.Text
        .Item("FirstName") = txtFirst.Text
        .Item("LastName") = txtLast.Text
        .Item("City") = tCity.Text
        .Item("Province") = tProvince.Text
        .Item("Active") = chkActive.Checked
        .Item("Balcony") = chkBalcony.Checked
        .Item("Smoking") = chkSmoking.Checked
        .Item("Description") = txtNotes.Text
    End With

    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand("SELECT * FROM tblHotelsA", conn)
            conn.Open()
            Dim da As New SqlDataAdapter(cmdSQL)
            Dim daU As New SqlCommandBuilder(da)
            da.Update(rstData)
        End Using
    End Using

    LoadGrid()

End Sub

So, the above should give you some ideas here.所以,上面应该给你一些想法。

I actually became tired of writing the same code to send a row of data to controls on a page, so I wrote a simple routine to do that for me.实际上,我已经厌倦了编写相同的代码来将一行数据发送到页面上的控件,所以我编写了一个简单的例程来为我做这件事。 Same goes for saving the data back to the table.将数据保存回表也是如此。

so, with a few helper routines, then you quite much just drag + drop to add controls to a page - and then a few helper routines.因此,使用一些辅助例程,您只需拖放即可将控件添加到页面 - 然后是一些辅助例程。

So, my load code, and save code to load up controls?那么,我的加载代码,并保存代码来加载控件? that is now a general routine and I thus don't even hand code that anymore.这现在是一般例程,因此我什至不再手动编写代码。

I adopted a extra attribute that I add to controls.我采用了一个添加到控件的额外属性。

So, my markup becomes say this:所以,我的标记变成这样说:

<div style="float:left" class="iForm">
 <label>HotelName</label>
 <asp:TextBox ID="txtHotel" runat="server"  width="280" f="HotelName" ></asp:TextBox> <br />
 <label>First Name</label>
 <asp:TextBox ID="txtFirst" runat="server" width="280" f="FirstName" ></asp:TextBox> <br />
    <label>Last Name</label>
    <asp:TextBox ID="txtLast" runat="server"  width="280" f="LastName"></asp:TextBox> <br />

So, in place of those multiple lines of code to load up the controls, I now can do this:所以,代替那些加载控件的多行代码,我现在可以这样做:

This:这个:

Sub EditOne(rstData As DataTable, btn As Button)

    With rstData.Rows(0)
        txtHotel.Text = .Item("HotelName").ToString
        txtFirst.Text = .Item("FirstName").ToString
        txtLast.Text = .Item("LastName").ToString
        tCity.Text = .Item("City").ToString
        tProvince.Text = .Item("Province").ToString
        chkActive.Checked = .Item("Active")
        chkBalcony.Checked = .Item("Balcony")
        chkSmoking.Checked = .Item("Smoking")
        txtNotes.Text = .Item("Description").ToString
    End With

    ' ok, div information filled out, now call our js pop function.
    Dim strHotelName = """Edit Information for " & rstData.Rows(0).Item("HotelName") & """"

becomes:变成:

    Call fLoader(HotelInfo, rstData.Rows(0))

So, now, it one line of code to load 5 or 25 controls with the data.所以,现在,只需一行代码就可以加载 5 个或 25 个控件的数据。

I can post that routine.我可以发布那个例程。

But, all in all?但是,总而言之?

You don't really write code to create the markup.您并没有真正编写代码来创建标记。 But, code behind supports the data operations of what you want to do against the controls.但是,后面的代码支持您想要对控件执行的数据操作。

So, some kind of on-the fly generation of markup?那么,某种即时生成的标记? Web forms not the best choice for that kind of design approach - it just not. Web 表单不是这种设计方法的最佳选择——它只是不是。

so, it rather difficult to generate controls and a id, but worse as you note, you have even more difficult time adding events to such controls.因此,生成控件和 id 相当困难,但正如您所注意到的,更糟糕​​的是,您更难以将事件添加到此类控件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM