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

时间:2015-05-14 11:58:28

标签: asp.net vb.net user-controls datalist dynamic-controls

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

在aspx页面的运行时,用户控制按照步骤加载,名称在db中定义,如下面的链接。

ASP.NET Custom user control to add dynamically

在第一步中,第一个用户控件是在page-init中绑定,用于显示.NET datalist控件中的预留可用性详细信息,如(参见图像)。

enter image description here

绑定所有细节以通过data-list的item_databound事件生成运行时控件。

  1. ImageOfRoom(asp.net Image Control) - 点击弹出窗口将打开滚动功能
  2. 名称(直接数据绑定)
  3. 设施(图标) - 从db。动态添加。
  4. 否。房间类型的房间类型(asp.net下拉控件) - 动态添加从数据库和选定的索引更改,需要在同一行中的另一个下拉绑定和成人下拉价格的变化将有所不同。
  5. 总价(直接数据包)
  6. 立即预订(按钮)
  7. enter image description here

    现在问题是每当任何datalist事件(点击romm-image或下拉选择索引改变)被触发时,动态控件就像ammenities,其他行的动态下拉等删除。

    我尝试过: - ispostback,页面生命周期的相关事件,ajax-jquery,viewstate。

    我也查了一下,但没有运气。 : Dynamically added controls in Asp.Net

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

    所以问题是如何在下拉选择索引更改或在usercontrol中的datalist中触发图像点击事件时保留动态控件及其值?

    我没有使用更新面板,这有用吗?如果是,那么请提供样本数据。

    很好地回答样本数据。即使请通过网格视图等任何其他控件建议,如果可能的话,我准备改变它。

    更新 这是我的代码

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

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

    在page_load和page_prerender(ispostback)中,下面的代码执行以加载运行时用户控件。

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

    usercontrol中的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项目数据绑定事件代码(其内部图像绑定,价格相关字段添加并根据条件创建动态控件)

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

    关于动态生成的下拉列表选择事件

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

    问题是这个事件删除了动态的其他控件,即使前一个选择的其他行被隐藏或丢失,所以我们在任何帖子后退和事件触发时保留动态控件。

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

3 个答案:

答案 0 :(得分:3)

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

我把这个过程分成两部分 1)将Gridview中当前的数据保存到会话变量中 2)重新创建,提供和绑定控件

这里保存gridview中的值。我使用我在这个网站上找到的递归查找控制公式(但不记得从哪里),因为我的控件生成并放在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

答案 1 :(得分:3)

在page_init

中完成所有操作

您正在ASP部件中连接事件处理程序,如下所示:

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

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

ComboBox.SelectedIndexChanged += new EventHandler(Dynamic_Method);

每次在webforms页面上执行动态内容时,所有设置(包括事件处理程序wireup )必须位于page_init中。当事件发生时,重新布线不会起作用。对于你正在做的事情(asp:......并且在方法调用期间),它最终会出现在生命周期的错误部分,而正确的事情并不是要添加javascript调用doPostback,或者运行__eventargs等,还有尚未构建的控件的数据(事件回发在AFTER页面初始化时检查,因此你必须在检查之前创建控件)因此被忽略。

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

我在一个大型应用程序上工作,该应用程序在page-init中动态构建webforms中的每个屏幕(来自UI生成器)。所有工作都是在活动中完成的,它们就像一个魅力! Page_load基本上是空的。了解asp页面生命周期 - 它是一个鼻屎但比在HotTowel中重写你的应用程序更容易(虽然想想下一个应用程序; - )

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

祝你好运!

答案 2 :(得分:0)

我已经做了以上建议和其他谷歌搜索网站的所有事情。但它每次重新绑定网格中的所有动态对象时都会刷新数据。

最后我基于javascript和jquery做了所有事情,没有那个动态控件总是重新绑定我不想要的东西。因此,任何陷入这种情况的机构都会忘记使用动态控件和javascript / webmethod进行操作。

感谢所有给出答案的人