当用户控件中的数据列表中触发下拉事件时,动态添加的控件将被删除

Dynamically added controls remove when dropdown event fired in the datalist in user control

我正在开发一个 ASP.NET VB.NET 网络表单 - 一个预订网络应用程序,其中只有一个 aspx 页面,其余页面是用户控制页面。

在 运行-aspx 页面时,用户控件根据数据库中定义的步骤和名称加载,如下面的 link.

ASP.NET Custom user control to add dynamically

在第一步中,第一个用户控件绑定到 page-init 中,用于在 .NET 数据列表控件中显示预订可用性详细信息(参见图片)。

所有细节都绑定到通过数据列表的 item_databound 事件生成 运行 时间控制。

  1. ImageOfRoom(asp.net 图像控件)- 单击弹出窗口将打开滚动功能
  2. 名称(直接数据绑定)
  3. 便利设施(图标)- 从数据库动态添加。
  4. 没有。每个房间类型的房间(asp.net 下拉控件)- 从数据库动态添加并在选定的索引更改时,需要在同一行中绑定另一个下拉列表,并且成人下拉列表的价格会有所不同。
  5. 总价(直接数据绑定)
  6. 立即预订(按钮)

现在的问题是,每当数据列表的任何事件(单击 romm-image 或下拉选择的索引发生变化)被触发时,动态控件都会删除,如便利设施、其他行的动态下拉列表等。

我尝试的是:- 是post返回,页面生命周期的相关事件,ajax-jquery,视图状态。

我也检查了这个,但没有运气。 : Dynamically added controls in Asp.Net

我分析说,用户控件总是反弹,然后触发事件,但没有数据列表重新绑定,因此没有 - 数据绑定事件触发,最后动态控制被删除。如果你愿意,我也会分享代码(但代码量很大)。

所以问题是,当下拉选择的索引发生变化或在用户控件的数据列表中触发图像点击事件时,如何保留动态控件及其值?

我没用过更新面板,可以吗?如果是,请给出样本数据。

很高兴用样本数据回答。甚至请建议,如果可能的话,可以通过任何其他控件(如 grid-view 或其他),然后我准备更改它。

已更新 这是我的代码

加载用户控制代码 在 aspx 页面中,usercontrol 定义为根据当前步骤加载另一个用户控件。 aspx页面中的这个“uc”用户控件标签。

<div id="divPlaceholder" runat="server">
        <uc:DynamicControlHost ID="ucDynamicControlHost" runat="server" />
 </div>

在page_load以及page_prerender(ispostback)中,下面的代码执行加载运行time user-control.

public Control SetUserControlPath(string path)
    {
        Control c = null;
        if (this.dynamicAllContent.Controls.Count > 0)
        {
            //Check that the new control is not the same as the current control
            if (!this.UserControlPath.Equals(path))
            {
                //Remove the old item because we can not simply replace them!
                this.dynamicPHAllContent.Controls.Clear();
                c = Page.LoadControl(path + ".ascx");
                c.ID = path;

                //Add New Item
                this.dynamicAllContent.Controls.Add(c);
                lock (_userControlLockObject)
                { 
                    //Store the new path
                    _strUserControl = path;
                }
            }
        }
        else
        {

                c = Page.LoadControl(path + ".ascx");
                c.ID = path;
                this.dynamicAllContent.Controls.Add(c);
                _strUserControl = path;

        }
        return c;
    }

用户控件中datalist的结构

<asp:UpdatePanel ID="EmployeesUpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>          
<asp:DataList ID="dlLodgingAvailableDetails" ShowHeader="true" OnSelectedIndexChanged="dlLodgingAvailableDetails_SelectedIndexChanged" runat="server" CellPadding="2" CellSpacing="2" BorderWidth="1px" BorderColor="Black" 
    OnItemDataBound="dlLodgingAvailableDetails_ItemDataBound" BorderStyle="Solid" GridLines="Horizontal" HorizontalAlign="Justify">
    <HeaderStyle CssClass="submit_butt"></HeaderStyle>
    <HeaderTemplate>           
     Lodging Item Type Details
     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
    <asp:Button ID="btnBookRoom" runat="server" Text="Book Rooms" CssClass="submit_butt" OnClick="btnBookRoom_Click" />
    </HeaderTemplate>        
    <ItemTemplate>
        <table cellpadding="2" cellspacing="0" border="1" style="width: 100%";>
            <tr>                
                <td style="width:170px">                    
                    <asp:ImageButton ID="imgLodging" OnClick="imgLodging_Click" commandargument='<%# Eval("ItemTypeId") %>'
                    runat="server" ImageUrl='<%# Eval("Photo") %>' Width="150px" Height="120px" />
                </td>               
                <td style="width:180px">
                <b>Name</b><br />
                 <span><%# Eval("ItemTypeName") %></span><br />
                <b>Occupancy</b>&nbsp;<span><%# Eval("Occupancy") %></span>
                    <br />&nbsp;
                    <asp:panel ID="placeholderAmmenities"  runat="server" Visible="True" ></asp:panel>
                 </td>
                <td style="width:100px">                    
                    <b>Room</b><br />
                     <asp:hiddenfield runat="server"  ID="hdnItemTypeId" Value='<%# Eval("LodgingItemTypeId") %>' />
                     <asp:DropDownList ID="ddlAvailable"  runat="server" 
                      AppendDataBoundItems="True" SelectedValue='<%# Bind("LodgingReservationsAvailable") %>' >
                         <asp:ListItem Value="0" Text="0"/>
                         <asp:ListItem Value="1" Text="1"/>
                         <asp:ListItem Value="2" Text="2"/>
                     </asp:DropDownList>                   
                </td>
                <td>

                </td>
                <td style="width:100px">
                    <div id="dvadult" runat="server"></div>
                    <asp:placeholder runat="server" ID="PlaceHolderAdult" ViewStateMode="Enabled" EnableTheming="False" Visible="True" ></asp:placeholder>
                </td>
                <td style="width:50px">
                      <asp:Label runat="server"  ID="lblnumbernight" ></asp:Label>
                </td>
                <td style="width:50px">
                      <asp:placeholder ID="placeholderPrice" runat="server" Visible="True"></asp:placeholder>
                </td>
                <td style="width:50px">
                 <b>Total</b><br />
                     <asp:Label runat="server" ID="lblTotalAmount" ></asp:Label>
                </td>
                <td style="width:100px">
                 <asp:Button ID="btnBookRoom" runat="server" Text="Book Rooms" CssClass="submit_butt" />
                </td>
            </tr>           
        </table>
    </ItemTemplate>
    <SeparatorStyle BackColor="Lime" Font-Bold="False" Font-Italic="False" Font-Overline="False" Font-Strikeout="False" Font-Underline="False" HorizontalAlign="Center" />
</asp:DataList>
</ContentTemplate>
</asp:UpdatePanel>

Datalist item数据绑定事件代码(里面的图片绑定,价格相关字段添加,也根据条件创建动态控件)

  protected void dlLodgingAvailableDetails_ItemDataBound(object sender, DataListItemEventArgs e)
    {
        try
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {                    
                Image img = e.Item.FindControl("imgLodging") as Image;
                if (img != null)
                {
                    string bytesval = ((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[3].ToString();
                    if (string.IsNullOrWhiteSpace(bytesval)) return;
                    byte[] bytes = (byte[])((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[3];
                    string base64String = Convert.ToBase64String(bytes, 0, bytes.Length);
                    img.ImageUrl = "data:image/png;base64," + base64String;
                }
                DropDownList ddlList = e.Item.FindControl("ddlAvailable") as DropDownList;
                Label lbldipositamount = e.Item.FindControl("lblTotalAmount") as Label;
                Label lblnumbernight = e.Item.FindControl("lblnumbernight") as Label;
                var PlaceHolderAmmenities = e.Item.FindControl("placeholderAmmenities") as Panel;
                ddlList.Attributes.Add("onchange", " openLodgingNumber1(this,'" + ddlList.SelectedValue + "');");
                int? LodgingItemTypeId = Convert.ToInt32(((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[1]);
                DataSet ds = new DataSet();
                ds = LodgingData.SelectLodgingItemTypeAmenityDateSet(LodgingItemTypeId);

                DataTable dt = new DataTable();
                if (ds != null)
                {
                    dt = ds.Tables[0];
                    if (dt.Rows.Count > 0)
                    {
                        for (int j = 0; j < dt.Rows.Count; j++)
                        {
                            Image image = new Image();
                            image.ID = "imgAmmenities" + j + DateTime.Now.ToString();
                            string bytesval = dt.Rows[j]["AmenityIcon"].ToString(); //((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[4].ToStrin();
                            //if (string.IsNullOrWhiteSpace(bytesval)) return;
                            if (bytesval != string.Empty)
                            {
                                byte[] bytes = (byte[])dt.Rows[j]["AmenityIcon"];
                                string base64String = Convert.ToBase64String(bytes, 0, bytes.Length);
                                image.ImageUrl = "data:image/png;base64," + base64String;
                                image.Height = 20;
                                image.Width = 20;
                                image.EnableViewState = true;                                    
                                PlaceHolderAmmenities.Controls.Add(image);
                                PlaceHolderAmmenities.Controls.Add(new LiteralControl("&nbsp;"));
                            }
                        }
                    }
                }

                decimal PriceTotal = 0;
                var PlaceHolderPrice = e.Item.FindControl("placeholderPrice") as PlaceHolder;
                DataSet dsprice = new DataSet();
                dsprice = LodgingData.SelectLodgingItemTypePrice(LodgingItemTypeId);
                if (dsprice != null)
                {
                    DataTable dtprice = new DataTable();
                    dtprice = dsprice.Tables[0];
                    if (dtprice.Rows.Count > 0)
                    {
                        DateTime fromdate = Convert.ToDateTime(txtFromDate.Text);
                        DateTime todate = Convert.ToDateTime(txtToDate.Text);
                        double daterange = ((todate - fromdate).TotalDays + 1);
                        lblnumbernight.Text = daterange.ToString();

                        //for (DateTime date = fromdate; date >= todate; date.AddDays(1))
                        for (int d = 0; d < Convert.ToInt32(daterange); d++ )
                        {
                            DateTime date = fromdate.AddDays(d);
                            //DataView dv = new DataView(dtprice);
                            DataTable dtprice1 = new DataTable();
                            DataRow[] rows = dtprice.Select("#" + date + "# >= PriceStartDate AND" + "#" + date + "# <= PriceEndDate");           
                            if (rows.Length > 0)
                            {
                                dtprice1 = rows.CopyToDataTable();
                            }
                            if (dtprice1.Rows.Count > 0)
                            {
                                for (int j = 0; j < dtprice1.Rows.Count; j++)
                                {
                                    Label lbl = new Label();
                                    string dayofweek = dtprice1.Rows[j]["DayOfWeekId"].ToString();
                                    if (dayofweek.Trim() == eDayOfWeek.All.ToString().Trim())
                                    {
                                        lbl.ID = "lbl" + j;
                                        lbl.Text = dtprice1.Rows[j]["Price"].ToString();
                                        PriceTotal += Convert.ToDecimal(dtprice1.Rows[j]["Price"]);                                            
                                        PlaceHolderPrice.Controls.Add(lbl);
                                        PlaceHolderPrice.Controls.Add(new LiteralControl("<br />"));
                                    }
                                    else if (Convert.ToInt32(dayofweek) == Convert.ToInt32(date.DayOfWeek + 1))
                                    {
                                        lbl.ID = "lbl" + j;
                                        lbl.Text = dtprice1.Rows[j]["Price"].ToString();
                                        PriceTotal += Convert.ToDecimal(dtprice1.Rows[j]["Price"]);
                                        PlaceHolderPrice.Controls.Add(lbl);
                                        PlaceHolderPrice.Controls.Add(new LiteralControl("<br />"));
                                    }
                                }
                            }
                            else
                            {
                                DataView dv1 = new DataView(dtprice);
                                dv1.RowFilter = "PriceStartDate IS NULL OR PriceEndDate IS NULL";
                                //dv1.RowFilter = "PriceStartDate == null and  PriceEndDate == null";
                                DataTable dtprice2 = new DataTable();
                                dtprice2 = dv1.ToTable();
                                for (int j = 0; j < dtprice2.Rows.Count; j++)
                                {
                                    Label lbl = new Label();
                                    string dayofweek = dtprice2.Rows[j]["DayOfWeekId"].ToString();
                                    if (dayofweek.Trim() == eDayOfWeek.All.ToString().Trim())
                                    {
                                        lbl.ID = "lbl" + j;
                                        lbl.Text = dtprice2.Rows[j]["Price"].ToString();
                                        PriceTotal += Convert.ToDecimal(dtprice2.Rows[j]["Price"]);
                                        PlaceHolderPrice.Controls.Add(lbl);
                                        PlaceHolderPrice.Controls.Add(new LiteralControl("<br />"));
                                    }
                                    else if (Convert.ToInt32(dayofweek) == Convert.ToInt32(date.DayOfWeek + 1))
                                    {
                                        lbl.ID = "lbl" + j;
                                        lbl.Text = dtprice2.Rows[j]["Price"].ToString();
                                        PriceTotal += Convert.ToDecimal(dtprice2.Rows[j]["Price"]);
                                        PlaceHolderPrice.Controls.Add(lbl);
                                        PlaceHolderPrice.Controls.Add(new LiteralControl("<br />"));

                                    }
                                }
                            }
                        }
                    }
                }
                lbldipositamount.Text = PriceTotal.ToString();
                // var amount = ((System.Data.DataRowView)(e.Item.DataItem)).Row.ItemArray[3];
                int selectedvalue = Convert.ToInt32(ddlList.SelectedItem.Text);
                if (selectedvalue != 0)
                {
                    double totalamount = selectedvalue * Convert.ToDouble(PriceTotal);
                    lbldipositamount.Text = totalamount.ToString();
                }
            }
        }
        catch (Exception)
        {
            throw;
        }
    }

触发动态生成的下拉选择事件

在上面甚至动态添加这个下拉列表,现在当调用这个控件的事件时,进一步的动态控制是根据条件添加的。

问题是此事件删除了动态其他控件,即使之前选择的其他行被隐藏或丢失,所以我们在任何 post 返回和事件触发中保留动态控件。

protected void ddlAvailable_SelectedIndexChanged(object sender, EventArgs e)
    {
        // if (UserControlTextBoxChanged != null) dlLodgingAvailableDetails_ItemDataBound(sender, e);
        //dlLodgingAvailableDetails.ItemDataBound += new DataListItemEventHandler(dlLodgingAvailableDetails_ItemDataBound);
        double amount = 0;
        var ddlList = (DropDownList)sender;
        var row = (DataListItem)ddlList.NamingContainer;
        //get the Id of the row
        DataSet ds = new DataSet();
        int? Id = Convert.ToInt32(((HiddenField)row.FindControl("hdnItemTypeId")).Value);
        double? tamount = Convert.ToDouble(((Label)row.FindControl("lblTotalAmount")).Text);
        int? groupid = Convert.ToInt32(ddlLodgingGroup.SelectedValue);
        int selectedvalue = Convert.ToInt32(ddlList.SelectedItem.Text);
        DateTime? startdate = Convert.ToDateTime(txtFromDate.Text);
        DateTime? enddate = Convert.ToDateTime(txtToDate.Text);
        ds = LodgingData.SelectLodgingItemTypeDataSet(startdate, enddate, groupid);
        DataTable dt = new DataTable();
        DataView dv = new DataView();
        if (ds != null)
        {
            dt = ds.Tables[0];
            dv = dt.DefaultView;
            dv.RowFilter = "LodgingItemTypeId=" + Id;
        }
        dt = dv.ToTable();
        if (dt.Rows.Count > 0)
        {
            if (tamount != null)
            {
                amount = Convert.ToDouble(tamount);
            }
        }
        //amount = Convert.ToDouble(((Label)row.FindControl("lblTotalAmount")).Text);            
        var PlaceHolder1 = ((PlaceHolder)row.FindControl("PlaceHolderAdult"));
        double totalamount = 0;
        if (selectedvalue != 0)
        {
            totalamount = selectedvalue * Convert.ToDouble(amount);
            ((Label)row.FindControl("lblTotalAmount")).Text = totalamount.ToString();
            Label lblAdult = new Label();
            lblAdult.ID = "lblAdult";
            lblAdult.Text = "Adult";
            lblAdult.Font.Bold = true;
            PlaceHolder1.Controls.Add(lblAdult);
            PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
        }
        else
        {
            totalamount = amount;
        }
        for (int j = 0; j < selectedvalue; j++)
        {
            DropDownList ComboBox = new DropDownList();
            ComboBox.ID = "ComboBox" + j;
            ComboBox.AutoPostBack = false;
            ComboBox.Attributes.Add("runat", "server");
            ComboBox.Items.Add(new ListItem("0", "0"));
            ComboBox.Items.Add(new ListItem("1", "1"));
            ComboBox.Items.Add(new ListItem("2", "2"));
            ComboBox.SelectedIndexChanged += new EventHandler(Dynamic_Method);
            PlaceHolder1.Controls.Add(ComboBox);
            PlaceHolder1.Controls.Add(new LiteralControl("<br />"));
        }
    }

我不确定这能为您解决多少问题,但这里有一个使用包含动态生成的下拉列表的模板字段在 gridview 中保留一行数据的示例

我把这个过程分成了两部分 1)将当前在Gridview中的数据保存到一个session变量中 2) 重新创建、获取和绑定控件

这里是将值保存在网格视图中。我使用在该站点上找到的递归查找控件公式(但不记得从哪里找到的),因为我的控件是生成的并放置在没有唯一名称的 gridview 行内。对于前。第 1 行中存在的 tbxA 与第 2 行中的 tbxA 不同。这可能不适用于您 - 关键是找到要保存其值的所有控件。

Private Sub SaveValues()
    Dim savedTable As New DataTable
    savedTable.Columns.Add(New DataColumn("A"))
    For i = 0 To GridView1.Rows.Count - 1
        Dim existing(0) As Object
        existing(0) = TryCast(FindControlRecursive(GridView1.Rows(i), "ddlA"), DropDownList).SelectedValue
        savedTable.Rows.Add(existing)
    Next
    Session("GhostTable") = savedTable
End Sub

然后在Page_Load下(当它是回发时)将gridview数据源设置为会话变量,并对其进行数据绑定。这将为每一行触发以下代码: 请记住,我还将下拉列表的数据源存储在页面加载时的会话变量中。这允许在每次生成下拉列表时进行数据源和数据绑定。

Protected Sub OnRowDataBound(sender As Object, e As GridViewRowEventArgs) Handles GridView1.RowDataBound
    'Handles databinding of each gridview1 row ddl to gridview templatefield
    If e.Row.RowType = DataControlRowType.DataRow Then
        Dim ddlA As New DropDownList()
        ddlA.DataSource = Session("lengthList")
        ddlA.DataBind()
        ddlA.ID = "ddlA"
        ddlA.SelectedValue = TryCast(e.Row.DataItem, DataRowView).Row.Item("A").ToString()
        e.Row.Cells(1).Controls.Add(ddlA)
    End if
End Sub

ddlA.SelectedValue = TryCast(e.Row.DataItem, DataRowView).Row.Item("A").ToString() 是在任何回发后保留数据的。它确定要绑定哪一行,然后用以前的内容重新填充控件。

希望对您有所帮助!

要确保每次都填充 gridview,请在事件处理程序中调用 SaveValues。

Protected Sub ddlEmpNumber_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ddlEmpNumber.SelectedIndexChanged
     'Do whatever on selected index change, then the following:
     Call SaveValues()
     GridView1.DataSource = Session("GhostTable")
     GridView1.DataBind()
End Sub

在 page_init

中完成所有操作

您正在像这样连接 ASP 部分中的事件处理程序:

<asp:DataList ID ... OnSelectedIndexChanged="dlLodgingAvailableDetails_SelectedIndexChanged"  ...

然后在处理程序的代码中尝试重新连接其他的:

ComboBox.SelectedIndexChanged += new EventHandler(Dynamic_Method);

任何时候你在网络表单页面上做动态的事情,所有设置包括事件处理程序连接必须在page_init.当事件 运行 时,重新布线将不起作用。对于您正在做的事情(asp:...以及在方法调用期间),它在生命周期的错误部分结束并且没有正确的东西来添加 javascript调用 doPostback,或者如果 运行s __eventargs 等具有尚未构建的控件的数据(在页面初始化后检查事件回发,因此您必须在此之前创建控件检查),因此被忽略。

注意 - 可能您知道这一点,但您必须为控件提供唯一 ID,如果您有一个数字主键,通常可以通过仅附加到数据行来完成。 (可能必须手动对用户控件中的子控件执行此操作,必须使用 page_init 中的用户控件执行此操作,希望你不会这样做)

我在开发一个大型应用程序,它在页面初始化中动态构建网络表单中的每个屏幕(来自 UI 生成器)。所有的工作都是在活动中完成的,他们的工作就像一个魅力! Page_load 基本上是空的。了解 asp 页面生命周期 - 这是一个鼻屎,但比在 HotTowel 中重写您的应用程序更容易(尽管考虑下一个应用程序 ;-)

很好的图表:http://blogs.msdn.com/b/aspnetue/archive/2010/01/14/asp-net-page-life-cycle-diagram.aspx

祝你好运!

我已经完成了上面建议的每件事,也完成了其他 google 搜索网站。但是它会刷新数据,并且每次都会重新绑定网格中的所有动态对象。

最后我完成了基于 javascript 和 jquery 的所有事情,没有我不想要的动态控制总是重新绑定。所以任何陷入这种情况的人都忘记了 r 和 d 并使用 javascript/ 带有动态控制的 webmethod。

感谢所有给出答案的人