0
votes

I'm working on an ASP.NET form based application.

I have a repeater bound to database. It has any of the the following controls per row:

RadioButtonList

TextBox

DropDownList

CheckBoxList

There are one of the following validation controls per row:

RequiredFieldValidator

CustomValidator

I have a button outside the repeater. When I click on save button, the code will loop through each repeater item, read selected data and saves it in database.

The problem I'm facing is as soon as I click on save button, it gives me error:

The ControlToValidate property of 'reqValidator' cannot be blank.

I made sure that repeater is loaded for the first time only and not when the page is posted back. Also, the code in save button does not seem to be executed. Here is my code:

<cms:CMSUpdatePanel runat="server" ID="updatePanelCampaignQuestions">
    <ContentTemplate>
         <asp:Repeater ID="repeaterQuestions" runat="server" OnItemDataBound="repeaterQuestions_ItemDataBound">
                <ItemTemplate>
                    <div class="repeater-container">
                        <asp:Label ID="lbQuestion" runat="server" Text='<%# Eval("Question") %>' />
                        <asp:Label ID="lbQuestionType" runat="server" Text='<%# Eval("QuestionType") %>' Style="display: inline; visibility: hidden" />
                        <asp:Label ID="lbAnswers" runat="server" Text='<%# Eval("Answers") %>' Style="display: inline; visibility: hidden" />
                        <asp:Label ID="lbArticleCampaignQuestionID" runat="server" Text='<%# Eval("ArticleCampaignQuestionID") %>' Style="display: inline; visibility: hidden" />

                        <div class="row validation-container">
                            <div class="col-md-12 col-lg-12">
                                <asp:TextBox ID="txtAnswer" CssClass="form-control" runat="server" TextMode="MultiLine" Rows="2" ValidationGroup="Campaign"></asp:TextBox>

                                <asp:RadioButtonList ID="rdAnswer" runat="server"></asp:RadioButtonList>

                                <asp:DropDownList ID="ddnAnswer" runat="server"></asp:DropDownList>

                                <asp:CheckBoxList ID="chkAnswer" CssClass="chkAnswer" runat="server"></asp:CheckBoxList>

                                <asp:RequiredFieldValidator ID="reqValidator" runat="server" Display="Dynamic" Style="color: #f00" />

                                <asp:CustomValidator ID="customValidator" runat="server" ClientValidationFunction="checkAnswer" Display="Dynamic" Style="color: #f00" />
                                <hr />
                            </div>
                        </div>
                    </div>
                </ItemTemplate>
            </asp:Repeater>

The code for repeater OnItemDataBound:

protected void repeaterQuestions_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            string questionType = (e.Item.FindControl("lbQuestionType") as Label).Text;
            RequiredFieldValidator reqValidator = (RequiredFieldValidator)e.Item.FindControl("reqValidator");
            CustomValidator customValidator = (CustomValidator)e.Item.FindControl("customValidator");

            if (questionType.ToLower().Equals("text"))
            {
                e.Item.FindControl("txtAnswer").Visible = true;
                e.Item.FindControl("rdAnswer").Visible = false;
                e.Item.FindControl("chkAnswer").Visible = false;
                e.Item.FindControl("ddnAnswer").Visible = false;

                reqValidator.ControlToValidate = e.Item.FindControl("txtAnswer").ID;
                reqValidator.ErrorMessage = "Please fill the answer";

                e.Item.Controls.Remove(customValidator);
            }
            else if (questionType.ToLower().Equals("single selection"))
            {
                e.Item.FindControl("txtAnswer").Visible = false;
                e.Item.FindControl("rdAnswer").Visible = true;
                e.Item.FindControl("chkAnswer").Visible = false;
                e.Item.FindControl("ddnAnswer").Visible = false;

                string strAnswers = (e.Item.FindControl("lbAnswers") as Label).Text;
                string[] answers = strAnswers.Split(new[] { "@@" }, StringSplitOptions.None);

                foreach(string answer in answers)
                {
                    (e.Item.FindControl("rdAnswer") as RadioButtonList).Items.Add(answer);
                }

                reqValidator.ControlToValidate = e.Item.FindControl("rdAnswer").ID;
                reqValidator.ErrorMessage = "Please select one";

                e.Item.Controls.Remove(customValidator);
            }
            else if (questionType.ToLower().Equals("drop down"))
            {
                e.Item.FindControl("txtAnswer").Visible = false;
                e.Item.FindControl("rdAnswer").Visible = false;
                e.Item.FindControl("chkAnswer").Visible = false;
                e.Item.FindControl("ddnAnswer").Visible = true;

                string strAnswers = (e.Item.FindControl("lbAnswers") as Label).Text;
                string[] answers = strAnswers.Split(new[] { "@@" }, StringSplitOptions.None);

                (e.Item.FindControl("ddnAnswer") as DropDownList).Items.Add(new ListItem("- Please Select -", "0"));

                foreach (string answer in answers)
                {
                    (e.Item.FindControl("ddnAnswer") as DropDownList).Items.Add(answer);
                }

                reqValidator.InitialValue = "0";
                reqValidator.ControlToValidate = e.Item.FindControl("ddnAnswer").ID;
                reqValidator.ErrorMessage = "Please select one";

                e.Item.Controls.Remove(customValidator);
            }            
            else if (questionType.ToLower().Equals("multiple selection"))
            {
                e.Item.FindControl("txtAnswer").Visible = false;
                e.Item.FindControl("rdAnswer").Visible = false;
                e.Item.FindControl("chkAnswer").Visible = true;
                e.Item.FindControl("ddnAnswer").Visible = false;

                string strAnswers = (e.Item.FindControl("lbAnswers") as Label).Text;
                string[] answers = strAnswers.Split(new[] { "@@" }, StringSplitOptions.None);

                foreach (string answer in answers)
                {
                    (e.Item.FindControl("chkAnswer") as CheckBoxList).Items.Add(answer);
                }

                e.Item.Controls.Remove(reqValidator);
                customValidator.ErrorMessage = "Please select at least one";
            }
        }
    }

The code for save button:

private void SaveAnswer()
    {
                int userID = GetUserID();
                int campaignID = GetCampaignID();

                foreach (RepeaterItem item in repeaterQuestions.Items)
                {
                    string answer = "";
                    string questionType = (item.FindControl("lbQuestionType") as Label).Text;
                    int articleCampaignQuestionID = int.Parse((item.FindControl("lbArticleCampaignQuestionID") as Label).Text);

                    if (questionType.ToLower().Equals("text"))
                    {
                        answer = (item.FindControl("txtAnswer") as TextBox).Text;
                    }
                    else if (questionType.ToLower().Equals("single selection"))
                    {
                        answer = (item.FindControl("rdAnswer") as RadioButtonList).SelectedItem.Text;
                    }
                    else if (questionType.ToLower().Equals("drop down"))
                    {
                        answer = (item.FindControl("ddnAnswer") as DropDownList).SelectedItem.Text;
                    }
                    else if (questionType.ToLower().Equals("multiple selection"))
                    {
                        CheckBoxList answerList = (item.FindControl("chkAnswer") as CheckBoxList);

                        foreach (ListItem checkItem in answerList.Items)
                        {
                            if (checkItem.Selected)
                            {
                                answer += checkItem.Text + "@@";
                            }
                        }

                        if (answer.EndsWith("@@"))
                            answer = answer.Substring(0, answer.Length - 2);
                    }

         // save value of answer to database
    }

I'm stuck on this for a very long time now. There is no other exception on the page other than the one mentioned above.

Edit

What is the flow of page postback?

Click on btnSaveAnswer , code for button executes , repeater is reloaded

Or

Click on btnSaveAnswer, repeater is reloaded , code for button executes

If I put repeater binding with:

if(!Page.IsPostBack)

I get the required field validator error

and

if I don't use above if, then I cannot read values from controls in repeater

1
which field is required? - see sharper
On every repeater row, there will be one control to which requiredfieldvalidator is bound. Custom validator is only for checkboxlist. The error says requiredfieldvalidator cannot be blank. - Ashutosh
You may get more help if you can simplify your code to the absolute minimum needed to reproduce the problem, which others can easily copy and paste. Copy your code to a standalone .aspx page and remove the following: CMSUpdatePanel, all the labels and divs, all but two types of input fields, and the CustomValidator. In the code-behind, bind the Repeater to a hard-coded data source, then show all the code in the class. And since the exception occurs as soon as you click Save, you probably don't need to include SaveAnswer. - Michael Liu
A RequiredFieldValidator needs a ControlToValidate property, as the error says.... <asp:RequiredFieldValidator ID="reqValidator" ControlToValidate="txtAnswer" - VDWWD

1 Answers

0
votes

I figured out the problem in my code. Here is what I did:

  1. Since my repeater is being built dynamically, I'm binding repeater every time and not using Page.IsPostBack

  2. Instead of binding repeater in Page_Load, I'm binding in Page_Init

This fixed my issue