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

发布于 2024-10-12 07:51:36 字数 5166 浏览 3 评论 0原文

首先,我了解需要在 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,文本描述。然后,我从数据集中的表中删除该行,并将其余项目绑定到复选框列表。

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

但就像我之前的所有人一样,我正在与页面周期进行邪恶的战斗……哈哈。

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

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

这是代码。这是从母版页运行的...

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

[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]
    &nbsp;
        [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;
    }

First I understand the need to build dynamic controls in the OnInit Section.

However, I read a document from Scott Guthrie?

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

So I got the impression from these blogs that if you add the control to the container then modify the properties, you can get at the control in the Page_Load.

In a nutshell, I have a table with a fk back to the table creating a hierarchy.
I load 3 usercontrols the page with checkbox lists that relate back through the parent key.

Table like this:

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

What my clients need is the ability to make a checkbox selection.
The child set of textboxes will display based on the parent.
If the txt_flag is set, a checkbox entry will not be populated.
Instead, they want the desc label printed out with a textbox for response.
The user data is not kept in the table above by the way.

So the issue I have is these text responses can be at any level of the custom control.
So I created a class with a 3 items ( id, literal control, and a textbox ).
I then dynamically create the controls based on the selection at any particular level.

I read each level into a dataset, I iterate through the dataset looking for that flag.
I capture an index variable in the rows with this flag and I create a List class to hold the
id, text_desc. I then remove the row from the table in the dataset and bind the remaining items to the checkboxlist.

I then go back to my control and write out dynamically the controls.

But like all those before me, I am doing evil battle against the Page Cycle...lol.

I cannot see the controls. I plan to DataBind() my controls separately on load as I have not gotten to the point where I'm getting the clients reponses from the database. That's for another day. The placeholder with my dynamic controls is OtherPlaceHolder. I have tried setting the Viewstate to true and false.

Any pointers on how to get the # of items on postback into a session variable so I can create the controls on the OnInit section.

Here is the code. This is being run from a Master Page...

On the controls, I changed the < & > to [ ] because this page that attempts to put code into
a controlbox with scrollbars was cutting off that code.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暗恋未遂 2024-10-19 07:51:36

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

On the assumption that when you say "I cannot see the controls" you mean that you're getting null references when you try to access them in the postback (rather than that the HTML doesn't contain them), have you tried using Page.EnsureChildControls()?

辞慾 2024-10-19 07:51:36

好的,如果我理解你的问题,你想保存你的控件并在回发时加载它们。您可以执行以下操作:

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

Ok If I understood your question right, you want to save your controls and load them back on postbacks. Here is what you can do:

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++;
        }
    }
}
°如果伤别离去 2024-10-19 07:51:36

对于不够明确,我深表歉意。

我相信当我创建控件时,我确实尝试在类中设置会话变量,并且它们在回发时为空。我尝试访问页面初始化中的会话变量并预加载和压缩。

我确实找到了解决这个问题的有趣方法。在 page_unload 上,我将控件解析为数据库 id 和 的哈希表的数组列表。用户输入的文本答案。

I apologize for lack of clarity.

I believe I did try setting Session variables in my classes when I created the controls and they were null on postback. I tried to access the session variable in the page init and preload and zip.

I did find an interesting workaround to this problem. On page_unload I parsed through the controls into an arraylist of hashtables of the database id & user'sentered text answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文