简体   繁体   中英

ASP.Net - Displaying a collection of controls

I am creating a simple form. I have created two simple classes, Question and QuestionSection.

I then create some subclasses of question, eg SimpleQuestion, MultipleChoiceQuestion, with different behaviour and markup.

QuestionSection has a property of a collection of questions, like so-

private List<Question> _Questions = new List<Question>();
public List<Question> Questions
{
    get { return _Questions; }
}

which is set on, say, SurveyForm.aspx like so-

<uc:QuestionSection ID="ucQuestionSection" runat="server">
        <questions> 
            <uc:SimpleQuestion ID="qFirstName" runat="server" QuestionText="First name" />
            <uc:SimpleQuestion ID="qLastName" runat="server" QuestionText="Last name" />
            <uc:MultipleChoiceQuestion ID="qEmail" runat="server" QuestionText="Email address" />
        </questions>
</uc:QuestionSection>  

On my QuestionSection.ascx page I have-

<div class="portlet-section-body form-fields">
    <asp:Panel ID="pnlQuestions" runat="server" ></asp:Panel>
</div>

which is load by this function on QuestionSection.ascx.cs

protected void Page_Init(object sender, EventArgs e)
{
      foreach (Question q in Questions)
      {
          pnlQuestions.Controls.Add(q);                
      }
}

I have a couple of questions-

  1. Is this a good idea?
  2. I am having some problems around postback and persistance of controls. My thinking is that these question controls are not dynamic, and so should work. However, on postback the question controls are not shown.
  3. Is there a better control to use in QuestionSection than the Panel control? I considered just using this.Controls.Add, but I can't see how I can add a div on either side of the control collection.

There are a couple of issues you raise. First of all, dynamically created controls don't properly persist on postback and must be re-created on each postback if you want their events to work.

Second, a better approach would be to use the control to create the questions. This control lets you define a pattern of controls to create.

I'm not sure what the HTML definition of the question object is, but here is an example of how you might modify QuestionSection.ascx to use a listview:

<div class="portlet-section-body form-fields">
    <asp:ListView runat="server" ID="QuestionsListView" 
        onitemcommand="QuestionsListView_ItemCommand">
        <LayoutTemplate>
            <div>
                <asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
            </div>
            <div>
                <asp:Button runat="server" ID="bnSave" Text="Save" 
                    CommandName="Save" />
                <asp:Button runat="server" ID="bnCancel" Text="Cancel" 
                    CommandName="Cancel" />
            </div>
        </LayoutTemplate>
        <ItemTemplate>
            <div class="QuestionRow">
                <asp:Label runat="server" Text='<%#Eval("QuestionText") %>' 
                    AssociatedControlID="tbAnswer"></asp:Label>
                <asp:TextBox runat="server" ID="tbAnswer"></asp:TextBox>
            </div>
        </ItemTemplate>
    </asp:ListView>
</div>

Here is the code behind to populate it and to handle the button click event. If you needed another event type, try to wire the events to the ListView control, itself, rather then the subcontrols:

protected void Page_Load(object sender, EventArgs e)
{
    List<string> Questions = new List<string>()
                                 {
                                     "First Name",
                                     "Last Name",
                                     "Email Address"
                                 };
    QuestionsListView.DataSource =
        from q in Questions
        select new
        {
            QuestionText = q
        };

    QuestionsListView.DataBind();
}

protected void QuestionsListView_ItemCommand
    (object sender, ListViewCommandEventArgs e)
{
    switch(e.CommandName)
    {
        case "Save":
            break;

        case "Cancel":
            break;
    }
}

For Part 3 - Is there a better control to use in QuestionSection than the Panel control?

Yes, the Placeholder control. It won't add a div around the controls.

Also, there is a dynamic placeholder control which aims to provide persistance to dynamic controls. However, I was unable to get this to work in my situation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM