【问题标题】:Adding Controls at runtime Form Builder在运行时添加控件 Form Builder
【发布时间】:2014-07-16 14:39:17
【问题描述】:

我正在使用以下代码向面板添加项目,但问题是它只允许我添加一个控件实例,我希望能够向面板添加任意数量的项目,我认为下面的代码可以实现这一点。

 if (ctrlType.SelectedValue == "TextBox")
        {
            listElements.Add(new XElement(@"TextBox", new XElement("name"),
                                  new XElement("Type", "System.String"),
                                    new XElement("displayName", this.txtTitle.Text.ToString()),
                                    new XElement("length", txtMaxLength.Text.ToString()),
                                     new XElement("key", false),
                                     new XElement("required",  chkRequired.Checked)));


            TextBoxUserControl tb2 =
                         (TextBoxUserControl)LoadControl(@"~\UserControls\TextBoxUserControl.ascx");
            tb2.XMLText = listElements;
            tb2.Text = txtTitle.Text;
            tb2.Name = "TextBox" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
            pnlControls.Controls.Add(tb2);

        }

        if (ctrlType.SelectedValue == "DropDown" && ctrlSource.SelectedValue == "0")   {
            listElements.Add(new XElement(@"ClassficationEnum", new XElement("name", "TestForm"),
                new XElement("Guid", "1f77f0ce-9e43-340f-1fd5-b11cc36c9cba"),
                                     new XElement("Type", "System.String"),
                                       new XElement("displayName", this.txtTitle.Text.ToString()),
                                       new XElement("length", txtMaxLength.Text.ToString()),
                                        new XElement("key", false),
                                        new XElement("required",  chkRequired.Checked)));


            Classfication clafficationDp =
                    (Classfication)LoadControl(@"~\UserControls\Classfication.ascx");
            clafficationDp.ID = "clafficationDp" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
            clafficationDp.Text = txtTitle.Text;
            pnlControls.Controls.Add(clafficationDp);



        }
        else if (ctrlType.SelectedValue == "DropDown" && ctrlSource.SelectedValue == "1")
        {
            listElements.Add(new XElement(@"SourceEnum", new XElement("name", "TestForm"),
                new XElement("Guid", "5d59071e-69b3-7ef4-6dee-aacc5b36d898.xml"),
                                     new XElement("Type", "System.String"),
                                       new XElement("displayName", this.txtTitle.Text.ToString()),
                                       new XElement("length", txtMaxLength.Text.ToString()),
                                        new XElement("key", false),
                                        new XElement("required", chkRequired.Checked)));



            SourceEnum dpsource =
                         (SourceEnum)LoadControl(@"~\UserControls\SourceEnum.ascx");
            dpsource.ID = "DropList" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
            dpsource.Text = txtTitle.Text;
            pnlControls.Controls.Add(dpsource);

        }
        UpdateActiveControl("Test", "Form Name", "Test Control", listElements);



        pnlControls.Controls.Add(new LiteralControl("<br />"));
  //      formControls = formGen.GetFormDataFromService();
        foreach (XElement formControl in listElements)
         {

             FormStructure frmstructure = new FormStructure();

             frmstructure.displayname = formControl.Element("displayName").Value;
             frmstructure.Required = Convert.ToBoolean(formControl.Element("required").Value);
             frmstructure.length = formControl.Element("length").Value;
             frmstructure.ControlType = formControl.Element("Type").Value;                


             formControls.Add(frmstructure);
         }

这是我加载表单控件详细信息的地方

 public partial class _default : System.Web.UI.Page
{

    PortalContext portalContext = new PortalContext();
    DataAccess da = new DataAccess();
    FormGenerator formGen = new FormGenerator();
    List<FormStructure> formControls = new List<FormStructure>();
    List<XElement> listElements = new List<XElement>();

    protected void Page_Load(object sender, EventArgs e)
    {
        da.SqlInstanceName = "CDDEVSVR-SQL";
        da.PortalDatabaseName = "PortalCms";
        da.IntegratedSecurity = true;
        SetEntityContextConnectionStrings();

        if (!IsPostBack)
        {
            formControls = formGen.GetFormDataFromService();
        }
        foreach (FormStructure formControl in formControls)
        {


            if (formControl.ControlType == "TextBox")
            {
                listElements.Add(new XElement(@"TextBox", new XElement("name"),
                                new XElement("Type", "System.String"),
                                  new XElement("displayName", this.txtTitle.Text.ToString()),
                                  new XElement("length", txtMaxLength.Text.ToString()),
                                   new XElement("key", false),
                                   new XElement("required", chkRequired.Checked)));



                TextBoxUserControl textBoxControl =
                    (TextBoxUserControl)LoadControl(@"~\UserControls\TextBoxUserControl.ascx");
                textBoxControl.XMLText = listElements;
                textBoxControl.Text = formControl.displayname;

                pnlControls.Controls.Add(textBoxControl);
                pnlControls.Controls.Add(new LiteralControl("<br />"));


            }

            if (formControl.ControlType == "DropDown")
            {
                listElements.Add(new XElement(@"ClassficationEnum", new XElement("name", "TestForm"),
                     new XElement("Guid", "1f77f0ce-9e43-340f-1fd5-b11cc36c9cba"),
                                          new XElement("Type", "System.String"),
                                            new XElement("displayName", this.txtTitle.Text.ToString()),
                                            new XElement("length", txtMaxLength.Text.ToString()),
                                             new XElement("key", false),
                                             new XElement("required", chkRequired.Checked)));


                SourceEnum dpsource =
                     (SourceEnum)LoadControl(@"~\UserControls\SourceEnum.ascx");
                dpsource.ID = "DropList" + " " + ctrlSource.SelectedValue.ToString() + " " + Guid.NewGuid().ToString();
                dpsource.Text = formControl.displayname;
                pnlControls.Controls.Add(dpsource);




            }
        }
    }

【问题讨论】:

  • 我不确定这有什么问题。为什么不能添加更多?他们在回发后消失了吗?是你的问题吗?
  • 在逻辑中没有任何地方将它们全部重新捕获,只需添加一个需要弄清楚

标签: c# asp.net


【解决方案1】:

我已经完成了一些业余水平的工作,以类似集合的方式将用户控件动态添加到 ASP.NET Web 表单中,并且能够使其正常工作。如果您的问题如@rene 建议的那样,您在回发中仅看到一个控件持续存在,则可能是由于this question answer 中描述的页面呈现过程问题以及@ovm 建议的那样;每个页面渲染都必须重新生成控件,我可以使用存储在专用会话变量中的数组来做到这一点。

也就是说,在开发该功能时,有几篇博客文章表明这​​不是一个好主意,并且看到它在页面生成和渲染中的工作方式,我同意。我不希望有一个轻松的时间来 ajax 页面的动态部分或稍后改进它。常见的(可能是两个博客)解决方法是设计为将您可能需要的所有控件都内置到页面中,然后隐藏并且不提供给定页面渲染不需要的控件。高温

【讨论】:

  • 在 OnInit 中预加载和隐藏除活动控件之外的所有控件也是我在更大的 WebForm 应用程序中所做的。但也有一个缺点:如果这些控件本身暴露了事件,那么管理回发会变得非常麻烦。因为这些控件可能是在回发期间添加的,所以在 Page_Load 函数中单独使用 Page.IsPostback 的常见(错误?)概念可能会给您带来麻烦。但是这个评论实际上只是关于 WebForms 架构的一个旁注。致 OP:我强烈建议改用 MVC,或保持 UserControl 结构尽可能简单。
  • @ovm 我的问题是当我点击添加按钮时它唯一获得一个控件的逻辑我不知道为什么
  • @ovm 查看我的编辑,我首先在其中加载信息,也许您可​​以对此有所了解
  • @stackUser83 你有一些实现的示例代码吗?
  • 我不确定这是你最大的问题。您确定您的 formControls = formGen.GetFormDataFromService(); 正在返回所有预期的控件吗?如果动态控件数据没有及时保存以供下一个页面渲染方法调用,这将有助于解释缺少的控件。
【解决方案2】:

您必须跟踪已添加到面板的所有控件,并在回发时重新添加它们。

如果这些控件应该是事件感知的,您应该在页面生命周期的 OnInit 阶段添加它们。

更新

您对 formControls 变量的初始化不能保证在多个请求中保持每个回发。您可以做的是跟踪 HttpContext.Current.Cache 中的 FormStructure 实例,并在 OnInit 阶段根据缓存中的 FormStructures 重新创建控件。

private List<FormStructure> GetFormStructureStore () {
  IList<FormStructure> formControls = (IList<FormStructure>)HttpContext.Current.Cache["FormControlsKey"];
  if(formControls == null)
  {
    formControls = new List<FormStructure>();
    HttpContext.Current.Cache.Add(formControls);
  }
  return formControls;
}

protected override void OnInit(EventArgs e)
{
  IList<FormStructure> formControls = GetFormStructureStore();
  // load the controls and add them to the Controls collection
  // ...
}

您现在可以使用此方法从缓存中获取 formControls 并删除页面级变量。

//List<FormStructure> formControls = new List<FormStructure>();

另外,你能告诉我们什么

formGen.GetFormDataFromService();

真的回来了吗?

我问这个是因为即使 formControls 的内容在 Session 中的某个时间点丢失,如果GetFormDataFromService() 返回多个 FormStructures,它们实际上应该是可见的。

【讨论】:

  • 我在我的 formControls 类中这样做了,我在它们中添加了控件,但它似乎失去了引用并且总是计数为一个
  • 如何在回发中持久化已添加的控件信息?你能告诉我们 formControls 变量的声明吗?
  • 看看List formControls = new List();我在 addcontrol 末尾添加到该列表
  • 我添加了一个示例,说明如何使用缓存来持久化元信息@user3824967
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
相关资源
最近更新 更多