为转发器中的文本框创建动态 ID

Creating dynamic id for textbox in repeater

所以我从 DB 获取信息并在 ASP 转发器中使用它来获取 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>

最多可以有10个选项。现在我想选择一个选项 (id=reasonStd) 并使用一个按钮将每个选项保存在数据库中,但我不知道如何获取转发器中每个项目的每个 id。

当我检查代码时,我可以看到下拉列表在前端创建得很好(reasonStd1248、reasonStd2371),但找不到调用它并将其保存到数据库的方法(我已经有了方法测试和 运行)。我试过类似...

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

好吧,问题是空值扭曲了事情。

(我同意这是一个问题+挑战)。

因此,推回值 - 通常不是问题。无论是文本框、复选框等 - 然后再没有真正的问题。

但是,组合框有两个问题。通常我们提供给它的列表没有空白(别无选择),更糟糕的是我们不能从数据库中提供一个空值加倍糟糕!!!

现在您的下拉列表(组合)充满了静态列表。但它可以很好地填充数据 table。我将 post 一个使用数据 table 驱动我们的“项目”(中继器)的示例,然后还包含一个下拉列表,该列表也来自 table 个选择。

所以,假设标记是这样的:

<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>

因此,在上面,我们有一些文本框、一个下拉列表和一个复选框。

您可以看到我们用 Eval() 填充了这些控件。

因此,填充中继器的代码如下所示:

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();
}
}

好的,上面的现在可以工作了。您会非常小心地注意到,我在 class 级别删除了 rstHotels 数据 table,因为我们稍后需要它。在我的例子中,因为我的下拉列表没有像你的那样的 static/fixed 来源,所以上面也会加载它。

结果是这样的:

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

将数据从中继器发送回填满中继器的相同 table。 (是的,我们确实坚持 table in Session().

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

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);
}
}

还有一个供参考:gridview、listview 和可能还有十几个控件?如果您不参加或没有替代模板,那么您不必担心也不必打扰。转发器控制是其中的一个例外。 (按照上面的规定,您必须测试项目行和替代行 - 我不知道为什么 - 但您必须这样做 - 不要离开该替代行)。

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

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

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

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 = "";
}
}

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

如前所述,我确实保留了导致整个混乱的数据 table,我这样做是为了轻松发送回数据库。您可以重新拉取或创建一个空白数据table (select id = 0,然后添加行,但鉴于数据集只有大约 20-40 个项目,然后持久化数据table 对 session() 系统的压力不大。

因此,第一页 post- 后台加载如下所示:

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"];
    }
}
}

以上是我如何保留 table,以及我们的下拉列表的 tblCity(您没有)。

因此,您必须在 itemdata 绑定上捕获 + 设置下拉列表。如果您在标记中只是设置下拉列表

,您可能不必这样做

例如:

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

但是,以上对我来说失败了,因为有些列还没有值,当您尝试 set/use 不存在的值时,组合框变得相当 mad/nasty .并在上面扔空值 - 它变得更糟。因此,我在 itemdatabound 中必须为每个“重复”项目填写下拉列表,因此我还必须将空白行选项添加到下拉列表中。然后我检查是否为 null,并插入空白(空字符串)或值。

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

理论上,更新代码应该 test/check 用于空字符串,如果这是您当前的约定,则将“null”保存回数据库。 (即:没有空值和空字符串,或者空值和没有空字符串)。所以,无论你现在有什么约定,都应该坚持。

如前所述,您不必在 itemdata 绑定中填充下拉列表,但您必须处理空值检查 - 如前所述,添加额外下拉选项(空白)的代码可能也可以被您跳过,并简单地添加到您的硬编码选择列表中。但是您仍然必须处理 null - 我在上面只是检查了一个空行值,并推入一个空字符串以使它起作用。