动态控件 - C# - CheckBoxList父级 - 子级

时间:2011-01-12 22:10:31

标签: c# asp.net dynamic controls

首先,我了解在OnInit部分中构建动态控件的必要性。

但是,我读了Scott Guthrie的文件?

http://scottonwriting.net/sowblog/archive/2004/10/08/162998.aspx

所以我从这些博客中得到的印象是,如果您将控件添加到容器然后修改属性,您可以获取Page_Load中的控件。

简而言之,我有一个表格,fk回到表格创建一个层次结构。 我在页面上加载3个用户控件,其中包含通过父键关联的复选框列表。

表格如下:

create table myTbl
(
id   int identity,
par_id int,
item_desc  varchar(25)
other_desc_flag bit
)

我的客户需要的是能够选择复选框。 子项集文本框将基于父项显示。 如果设置了txt_flag,则不会填充复选框条目。 相反,他们希望打印出带有文本框的desc标签以进行响应。 顺便说一句,用户数据不会保存在上表中。

所以我遇到的问题是这些文本响应可以在自定义控件的任何级别。 所以我创建了一个包含3个项目(id,文字控件和文本框)的类。 然后,我根据任何特定级别的选择动态创建控件。

我将每个级别读入数据集,我遍历数据集以查找该标志。 我使用此标志捕获行中的索引变量,并创建一个List类来保存 id,text_desc。然后,我从数据集中的表中删除该行,并将其余项绑定到复选框列表。

然后我回到我的控制并动态写出控件。

但是和我之前的所有人一样,我正在与Page Cycle进行邪恶的战斗......哈哈。

我看不到控件。我计划在加载时单独使用DataBind()我的控件,因为我还没有达到客户端从数据库响应的程度。那是另一天。我的动态控件的占位符是OtherPlaceHolder。我已经尝试将Viewstate设置为true和false。

关于如何将回发中的项目数量转换为会话变量的任何指针,以便我可以在OnInit部分创建控件。

这是代码。这是从Master Page ...

运行的

在控件上,我更改了< &安培; >到[]因为这个页面试图将代码放入 带有滚动条的控制箱正在切断该代码。

[asp:UpdatePanel ID="UpdPanel" runat="server" EnableViewState="true" UpdateMode="Always"]
[ContentTemplate]
     [asp:Table runat="server" ID="ContainerTbl"]
            [asp:TableHeaderRow]
                 [asp:TableHeaderCell ColumnSpan="2" CssClass="tdCell"][asp:Literal ID="LitDesc" runat="server" Text="Level" /][/asp:TableHeaderCell]
            [/asp:TableHeaderRow]
            [asp:TableRow]
                [asp:TableCell runat="server" ID="tblItems" VerticalAlign="top"]
                    [asp:PlaceHolder runat="server" ID="CtrlPlaceHolder"]
                       [asp:CheckBoxList ID="cboItems"  Visible="false" runat="server" AutoPostBack="true"][/asp:CheckBoxList]
                       [asp:HiddenField ID="otherCnt" runat="server" /]
                    [/asp:PlaceHolder]
                    [asp:PlaceHolder runat="server" ID="OtherPlaceHolder"  EnableViewState="false"]
                    [/asp:PlaceHolder]
                [/asp:TableCell]
           [/asp:TableRow]

            [asp:TableRow]
                [asp:TableCell  VerticalAlign="top"]
                    [asp:Label ID="LabMsg" runat="server" CSSClass="tdCell" Font-Bold="true" Visible="false"/]
                [/asp:TableCell]
            [/asp:TableRow]
        [/asp:Table]
     
        [asp:HiddenField ID="hLevel"  runat="server" Value="" /]

[/ContentTemplate]
[/asp:UpdatePanel]
 private void WriteOutQuestions(List<Questions> qList)
    {
        int itemCnt = 1;

        // clear any controls in other place holder first. 
        OtherPlaceHolder.Controls.Clear();
        Table OTD = new Table();
        foreach (Questions qst in qList)
        {
            // we're going to create the new control and add to 
            // the placeholder - OtherPlaceholder
            // we'll then reference those controls and add the data to those
            // controls. 
            // see dynamic control article: http://scottonwriting.net/sowblog/archive/2004/10/08/162998.aspx

            HiddenField hItemId = new HiddenField();
            TextBox txtItem = new TextBox();
            LiteralControl ltcItem = new LiteralControl();
            // add the new controls
            string strItemId = "hItem" + Convert.ToString(itemCnt);
            string strTxtItem = "txtItem" + Convert.ToString(itemCnt);
            string strLtcItem = "ltcItem" + Convert.ToString(itemCnt);
            hItemId.ID = strItemId;
            hItemId.EnableViewState = true;
            txtItem.ID = strTxtItem;
            txtItem.EnableViewState = true;
            ltcItem.ID = strLtcItem;
            ltcItem.EnableViewState = true;
            OTD.Controls.Add(OtherDescAddControl(OtherPlaceHolder, hItemId, ltcItem, txtItem));

            // now reference the new added controls and set values from Question object...

            ++itemCnt;
        }
        OtherPlaceHolder.Controls.Add(OTD);
        // now post data to controls...
        itemCnt = 1;
        foreach (Questions qst in qList)
        {
            string strItemId = "hItem" + Convert.ToString(itemCnt);
            string strTxtItem = "txtItem" + Convert.ToString(itemCnt);
            string strLtcItem = "ltcItem" + Convert.ToString(itemCnt);
            HiddenField hfld = (HiddenField)OtherPlaceHolder.FindControl(strItemId);
            TextBox txtBox = (TextBox)OtherPlaceHolder.FindControl(strTxtItem);
            LiteralControl ltx = (LiteralControl)OtherPlaceHolder.FindControl(strLtcItem);
            hfld.Value = qst.HFld.ToString();
            txtBox.Text = qst.TxtBox;
            txtBox.Attributes.Add("class", "txtBox");
            ltx.Text = qst.Ltc.ToString();
            ++itemCnt;
        }
        //decrement itemCnt and populate box here...
        --itemCnt;
        HiddenField hfldCnt = (HiddenField)CtrlPlaceHolder.FindControl("otherCnt");
        hfldCnt.Value = Convert.ToString(itemCnt);
        hfldCnt.Visible = true;
    }

3 个答案:

答案 0 :(得分:0)

假设当你说“我看不到控件”时你的意思是当你试图在回发中访问它们时(而不是HTML不包含它们)你得到空引用,是吗?尝试使用Page.EnsureChildControls()?

答案 1 :(得分:0)

好的如果我理解你的问题,你想要保存你的控件并将它们加载回回发。您可以这样做:

List<HiddenField> HiddenFields = new List<HiddenField>{};
List<TextBox> TextBoxs = new List<TextBox>{};
List<LiteralControl> LiteralControls = new List<LiteralControl>{};


OTD.Controls.Add(OtherDescAddControl(OtherPlaceHolder, hItemId, ltcItem, txtItem));
// do this for all your items that you load to page (add them to your list).
HiddenFields.Add(hItemId);
// when you are done with loading all your controls to page, add your populated Lists                        to session. 
Session["HiddenFields"] = HiddenFields;


//On Page_Init or Page_Load, simpy load them back IF **page is postback**.
If(Page.IsPostBack)
{
    LoadControlsFromSession();
}

private void LoadControlsFromSession()
{
    HiddenFields = Session["HiddenFields"] as List<HiddenFields>;
    // Load all your List objects from session like above.
    int counter = 0;
    if(HiddenFields != null)
    {
        foreach(HiddenField hdnField in HiddenFields)
        {
            //load your objects with the same method you have from your List.
            OTD.Controls.Add(OtherDescAddControl(OtherPlaceHolder, HiddenFields[counter], LiteralControls[counter], TextBoxs[counter]));
            counter++;
        }
    }
}

答案 2 :(得分:0)

我为不清楚而道歉。

我相信我在创建控件时尝试在我的类中设置Session变量,并且在回发时它们为null。我试图在页面init和preload和zip中访问session变量。

我确实找到了解决这个问题的有趣方法。在page_unload上,我通过控件解析为数据库id&amp;的哈希表的arraylist。用户的文本答案。