【问题标题】:Dynamic Controls - C# - CheckBoxList Parent - Children动态控件 - C# - CheckBoxList 父级 - 子级
【发布时间】:2011-06-08 03:45:51
【问题描述】:

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

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

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

我看不到控件。我计划在加载时分别对我的控件进行 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]
     
        [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;
    }

【问题讨论】:

    标签: c# asp.net dynamic controls


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        对于表述不够清晰,我深表歉意。

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

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

        【讨论】:

          猜你喜欢
          • 2011-07-22
          • 2018-10-06
          • 2017-12-03
          • 2020-10-08
          • 1970-01-01
          • 1970-01-01
          • 2014-02-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多