为转发器中的文本框创建动态 ID [英] Creating dynamic id for textbox in repeater

查看:45
本文介绍了为转发器中的文本框创建动态 ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我从 DB 获取信息并在 ASP 中继器中使用它来获取表格.

 

您会在上面注意到,我们有一个保存按钮.保存按钮代码是这样做的:

将数据从转发器发送回填充转发器的同一个表.(是的,我们确实并且确实在 Session() 中保留了该表.

所以,代码真的很简单——而且代码不多:

protected void cmdSave_Click(object sender, EventArgs e){//将转发器行拉回表.foreach (RepeaterItem rRow in Repeater1.Items){int RecordPtr = rRow.ItemIndex;DataRow OneDataRow;OneDataRow = rstTable.Rows(RecordPtr);OneDataRow.Item("HotelName") = rRow.FindControl("txtHotelName") as TextBox.Text;OneDataRow.Item("FirstName") = rRow.FindControl("txtFirst") as TextBox.Text;OneDataRow.Item("LastName") = rRow.FindControl("txtLast") as TextBox.Text;OneDataRow.Item("City") = rRow.FindControl("cboCity") as DropDownList.Text;OneDataRow.Item(Active") = rRow.FindControl(chkActive") as CheckBox.Checked;}//现在将带有更新的表发送回数据库string strSQL = "SELECT ID, FirstName, LastName, City, HotelName, Active from tblHotels WHERE ID = 0";使用 (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3))){cmdSQL.Connection.Open();SqlDataAdapter daupdate = 新的 SqlDataAdapter(cmdSQL);SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);daupdate.Update(rstTable);}}

仅供参考:虽然 gridview、listview 和可能还有 DOZEN 更多控件?如果您不参加或没有替代模板,那么您不用担心也不要打扰.中继器控制是这些例外之一.(按照上面的方式,您必须同时测试项目行和替代行 - 我不知道为什么 - 但您必须这样做 - 不要离开该替代行检查).

好的,以上所做的就是循环转发器,并将值发送回表.然后我们拿表,并执行一个单一的 .update 命令.

所以,现在唯一真正的问题是处理空下拉列表.

您在 itemdata 绑定事件中处理该问题.像这样说:

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e){//设置组合框数据源if (e.Item.ItemType == ListItemType.Item | e.Item.ItemType == ListItemType.AlternatingItem){//设置下拉列表//int ix = e.Item.ItemIndex;DropDownList cboDrop = e.Item.FindControl(cboCity");cboDrop.DataSource = rstCity;cboDrop.DataBind();cboDrop.Items.Insert(0, new ListItem(string.Empty));//添加空行if (IsDBNull(rstTable.Rows(ix).Item("City")) == false)cboDrop.Text = rstTable.Rows(ix).Item(City");别的cboDrop.Text = "";}}

现在在您的代码中?您可以跳过填充 + 数据绑定,但请注意最后一点 - 测试/检查空值.还要注意我是如何在下拉列表中添加一个额外的空白选项的.您需要那个空白的额外选择,因为许多数据行可能还没有选定的值.并且您不能推入空值,并且您不能推入一个exmpty 字符串,直到允许空白的空字符串选项被添加到下拉列表中.现在在您的情况下,因为它是硬编码 - 那么您可以在标记中添加额外的空白选项 - 我不能,因为我的下拉列表是数据库驱动的.

如前所述,我确实并且确实保留了导致整个混乱的数据表,我这样做是为了轻松发送回数据库.您可以重新拉取或创建一个空白数据表(选择 id = 0,然后添加行,但考虑到数据集只有大约 20-40 个项目,那么持久化数据表对会话来说不是很大的压力() 系统.

所以,第一页回传加载看起来像这样:

private DataTable rstTable = new DataTable();私有数据表 rstCity = 新数据表();protected void Page_Load(object sender, System.EventArgs e){如果(System.Web.UI.Page.IsPostBack == false){加载网格();System.Web.UI.Page.Session[MyTable"] = rstTable;System.Web.UI.Page.Session[MyCity"] = rstCity;}别的{rstTable = System.Web.UI.Page.Session[MyTable"];rstCity = System.Web.UI.Page.Session[MyCity"];}}}

以上是我对表格和下拉列表的 tblCity(您没有)的方式.

因此,您必须在 itemdata 绑定上捕获并设置下拉列表.如果您在标记中只是设置下拉列表,您可能不必这样做

例如:

Text = '<%# Eval("City") %>'

但是,以上对我来说失败了,因为有些列还没有值,并且当您尝试设置/使用不存在的值时,组合框会变得相当疯狂/讨厌.并在上面折腾空值 - 它变得更糟.因此,我在 itemdatabound 中必须为每个重复"填充下拉列表.item,因此我还必须将空白行选项添加到下拉列表中.然后我检查 null,并输入一个空白(空字符串)或值.

请注意,如果您仔细观察,上面发布的代码将导致文本框和值为 null 的空字符串.您可以自由地将数据行中的 null.Item() 分配给文本框,但您不能将下拉列表中的文本设置为 null - 因此我们使用 itematabound 来设置我们的下拉列表.

理论上,更新代码应该测试/检查空字符串,并保存一个空"字符串.如果这是您当前的惯例,则添加到数据库.(即:要么没有空值和空字符串,要么没有空值和空字符串).所以,你应该坚持你现在拥有的任何约定.

如前所述,您不必在绑定的 itemdata 中填充下拉列表,但您必须处理空值检查 - 如前所述,添加额外下拉选项(空白)的代码也可以是被您跳过,只是添加到您的硬编码选择列表中.但是您仍然必须处理空值 - 我上面只是检查空行值,然后输入一个空字符串以使其工作.

So I am getting information from DB and using it in an ASP repeater to get a table.

    <asp:Repeater ID="repS" runat="server">
                        <ItemTemplate>
                                            <a class="card-title text-secondary" href="#">
                                                <%#Eval("FirstName") %>
                                                <%#Eval("LastName") %> 
                                            (<%#Eval("Id")%>)
                                            </a>
                                            <asp:DropDownList ID="reasonStd<%#Eval("Id")%>" runat="server">
                                                <asp:ListItem Enabled="true" Text="Select Month" Value="-1"></asp:ListItem>
                                                <asp:ListItem Text="1" Value="1"></asp:ListItem>
                                                <asp:ListItem Text="2" Value="2"></asp:ListItem>
                                                <asp:ListItem Text="3" Value="3"></asp:ListItem>
                                                ...
                                            </asp:DropDownList>
                                            <span>

It can go as long as 10 options. Now I want to choose an option (id=reasonStd) and I use a button to save each option in the DB, but I do not get how can I get each id for each item in the repeater.

When I inspect the code I can see the dropdownlist creates it just fine in the front end (reasonStd1248, reasonStd2371), but can't find a way to call it and save it to the DB (I already have the method tested and running). I tried something like...

foreach (objetType obj in DataSource)
            {
                saveObject(obj, reasonStd+obj.Id+.Text.SelectedValue);
            }

解决方案

Ok, then, the issue is the nulls twisting things up.

(and I agree this is a probelm + challenge).

So, shoving back the values - in general not a issue. And be it a text box, check box etc. - then again no real issues.

However, the combo box has two problems. Often the list we feed it does NOT have a blank (no choice), and MUCH WORSE is we can't feed it a null value from the database DOUBLE WORSE!!!

Now your droplist (combo) is filled with a static list. But it could VERY well be filled with a data table. I'll post a example with a data table driving our "items" (the repeater), and then also include a dropdown list that ALSO is from a table of choices.

so, say the markup is like this:

<asp:Repeater ID="Repeater1" runat="server">
    <ItemTemplate>
        <div style="border-style:solid;color:black;width:250px;float:left">

        <div style="padding:5px;text-align:right">
            Hotel Name: <asp:TextBox ID="txtHotelName" runat="server" Text ='<%# Eval("HotelName") %>' Width="130px" />
            <br />
            First Name: <asp:TextBox ID="txtFirst" runat="server" Text ='<%# Eval("FirstName") %>'  Width="130px" />
            <br />
            Last Name: <asp:TextBox ID="txtLast" runat="server" Text ='<%# Eval("LastName") %>'  Width="130px" />
            <br />
            City : <asp:DropDownList ID="cboCity" runat="server" DataTextField="City" 
                DataValueField="City" Width="130px">
                </asp:DropDownList>
            <br />
            Active: <asp:CheckBox ID="chkActive" runat="server" Checked = '<%# Eval("Active") %>'/>
        </div>
    </div>

    </ItemTemplate>

</asp:Repeater>

So, in above, we have a some text boxes, a drop down, and a check box.

YOu can see that we fill these controls with Eval().

So, the code to fill the repeater looks like this:

public void LoadGrid()
{

// load up our drop down list from database
string strSQL;
strSQL = "SELECT City from tblCity Order by City";
using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
    cmdSQL.Connection.Open();
    rstCity.Load(cmdSQL.ExecuteReader);
}

// now load up our repeter

strSQL = "SELECT ID, FirstName, LastName, HotelName, City, Active from tblHotels ORDER BY HotelName";

using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
    cmdSQL.Connection.Open();
    rstTable.Load(cmdSQL.ExecuteReader);

    Repeater1.DataSource = rstTable;
    Repeater1.DataBind();
}
}

Ok, the above is now working. You will NOTE very carefull that I delcare both the rstHotels datatable at the class level, since we need it later. And in my case, since my droplist does NOT have a static/fixed source like yours, then above also loads that up.

the result is this:

You will note in above, we have a save button. The save button code does this:

Send data from repeater BACK TO THE SAME table that filled the repeater. (yes, we do and did persist that table in Session().

So, the code is really simple - and not a lot of code:

protected void cmdSave_Click(object sender, EventArgs e)
{

// pull repeater rows back to table.

foreach (RepeaterItem rRow in Repeater1.Items)
{
    int RecordPtr = rRow.ItemIndex;
    DataRow OneDataRow;

    OneDataRow = rstTable.Rows(RecordPtr);

    OneDataRow.Item("HotelName") = rRow.FindControl("txtHotelName") as TextBox.Text;
    OneDataRow.Item("FirstName") = rRow.FindControl("txtFirst") as TextBox.Text;
    OneDataRow.Item("LastName") = rRow.FindControl("txtLast") as TextBox.Text;
    OneDataRow.Item("City") = rRow.FindControl("cboCity") as DropDownList.Text;
    OneDataRow.Item("Active") = rRow.FindControl("chkActive") as CheckBox.Checked;
}

// now send table back to database with updates
string strSQL = "SELECT ID, FirstName, LastName, City, HotelName, Active from tblHotels WHERE ID = 0";

using (SqlCommand cmdSQL = new SqlCommand(strSQL, new SqlConnection(My.Settings.TEST3)))
{
    cmdSQL.Connection.Open();
    SqlDataAdapter daupdate = new SqlDataAdapter(cmdSQL);
    SqlCommandBuilder cmdBuild = new SqlCommandBuilder(daupdate);

    daupdate.Update(rstTable);
}
}

And a FYI: While gridview, listview and probably a DOZEN more controls? If you don't drop in or have a alternatving template, then you don't worry and don't bother. The repeater ocntrol is one of those exceptions. (you as per above have to test for both a item row, and the alternative row - I have no idea why - but you MUST do this - don't leave that alternative row check out).

Ok, so all the above does is loop the repeater, and send the values back to the table. And then we take the table, and execute a SINGLE .update command.

So, the ONLY real issue now is to deal with the null drop down list.

You deal with that issue in the itemdata bound event. Say like this:

protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{

// set combo box data source
if (e.Item.ItemType == ListItemType.Item | e.Item.ItemType == ListItemType.AlternatingItem)
{

    // setup drop down list
    // 
    int ix = e.Item.ItemIndex;
    DropDownList cboDrop = e.Item.FindControl("cboCity");
    cboDrop.DataSource = rstCity;
    cboDrop.DataBind();
    cboDrop.Items.Insert(0, new ListItem(string.Empty));     // add blank row

    if (IsDBNull(rstTable.Rows(ix).Item("City")) == false)
        cboDrop.Text = rstTable.Rows(ix).Item("City");
    else
        cboDrop.Text = "";
}
}

Now in YOUR code? You can skip the fill + data bind, but note that last bit - the test/check for nulls. And ALSO note how I added a extra BLANK selection in the drop list. You need that blank extra choice, since many of the rows of data may VERY well not yet have a selected value. And you can't shove in null, and you can't shove in a exmpty string UNTILL such time that allowing blank empty string option is ADDED to the drop down ist. Now in your case, since it is hard code - then you could add the extra blank choice in your markup - I could not, since my drop list was database driven.

As noted, I did and do persist the data table that drives the whole mess and I did this for easy sending back to the database. You could re-pull or create a blank datatable (select id = 0, and then do add rows, but given that the data sets are only about say 20-40 items, then persisting the data table is not a large strain on the session() system.

So, the first page post-back load looks like this:

private DataTable rstTable = new DataTable();
private DataTable rstCity = new DataTable();

protected void Page_Load(object sender, System.EventArgs e)
{
    if (System.Web.UI.Page.IsPostBack == false)
    {
        LoadGrid();
        System.Web.UI.Page.Session["MyTable"] = rstTable;
        System.Web.UI.Page.Session["MyCity"] = rstCity;
    }
    else
    {
        rstTable = System.Web.UI.Page.Session["MyTable"];
        rstCity = System.Web.UI.Page.Session["MyCity"];
    }
}
}

So above is how I persited the table, and our tblCity for the drop down list (which you don't have).

So, you have to catch + set the dropdown list on itemdata bound. You could perahps NOT have to do this if you in the markup were to just set the dropdown list

eg:

Text = '<%# Eval("City") %>'

But, the above fails for me, since some columns don't have a value yet, and the combo box gets rather mad/nasty when you attempt to set/use values that don't exist. And toss nulls on top that - it gets even worse. So, I in itemdatabound have to fill the dropdown list for each "repeating" item, and I thus also have to add the blank row choice to the dropdown. I then check for null, and shove in a blank (empty string), or the value.

Note that if you look close, the above posted code will thus result in emptry strings for text boxes and values that were null. You can freely assign a null.Item() from the data row to a text box, but you can't set Text from dropdown list to null - hence we used itematabound to setup our dropdown list.

In theory, the update code should test/check for empty strings, and save back a "null" to the database if that is your current convention. (ie: either no nulls and empty strings, or nulls and no empty strings). So, one should stick to which ever convention you have now.

As noted, you don't have to fill the drop list in itemdata bound, but you DO HAVE to deal with the null values check - and as noted the code that adds that extra dropdown choice (blank one) could also be skipped by you, and simply added to your hard coded list of choices you have. But you still have to deal with the null - and I above simply check for a null row value, and shove in a empty string for this to work.

这篇关于为转发器中的文本框创建动态 ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆