【问题标题】:Retrieve SelectedValues of a dynamically generated control检索动态生成的控件的 SelectedValues
【发布时间】:2014-09-07 03:37:49
【问题描述】:

我正在努力思考如何生成动态控件。我有一个 Button1_Clickevent,它根据数据库中字段的值创建 CheckBoxList (id=cblAnswers) 或 RadioButtonList (id=rblAnswers)。

在 Button3_Click 事件中,我希望能够从生成的控件中检索选定的值,并将它们与列表 listOfCorrectAnswerIDs 进行比较。如果所选值与 listOfCorrectAnswerIDs 中的值完全匹配,我想设置一个变量。

我可以创建控件,但如何在 Button3_Click 中检索选定的值并将它们与 List listOfCorrectAnswerIDs 进行比较?

protected void Button1_Click(object sender, EventArgs e)
{
    string connStr = ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
    MySqlConnection conn = new MySqlConnection(connStr);
    MySqlDataReader reader;

    List<string> listOfAnswerIDs = new List<string>();
    List<string> listOfAnswers = new List<string>();
    List<string> listOfCorrectAnswerIDs = new List<string>();

    try
    {
        conn.Open();
        string cmdText = "SELECT * FROM questions_m WHERE question_id=1";
        MySqlCommand cmd = new MySqlCommand(cmdText, conn);

        reader = cmd.ExecuteReader();

        if (reader.Read())
        {
            lblQuestion.Text = reader["question"].ToString();

            if (reader["type"].ToString().Equals("C"))
            {
                CheckBoxList cblAnswers = new CheckBoxList();
                cblAnswers.ID = "cblAnswers";
                Page.Form.Controls.Add(cblAnswers);
            }
            else if (reader["type"].ToString().Equals("R"))
            {
                 RadioButtonList rblAnswers = new RadioButtonList();
                 rblAnswers.ID = "rblAnswers";
                 Page.Form.Controls.Add(rblAnswers);
            }

            ViewState["QuestionID"] = reader["question_id"].ToString();
            reader.Close();

            string cmdText2 = "SELECT * FROM answers_m WHERE question_id=1";
            MySqlCommand cmdAnswers = new MySqlCommand(cmdText2, conn);
            reader = cmdAnswers.ExecuteReader();

            while (reader.Read())
            {
                listOfAnswerIDs.Add(reader["answer_id"].ToString());
                listOfAnswers.Add(reader["answer"].ToString());
                if (reader["correct"].ToString().Equals("Y"))
                {
                    listOfCorrectAnswerIDs.Add(reader["answer_id"].ToString());
                }
            }

            reader.Close();
            populateAnswers(listOfAnswers, listOfAnswerIDs);

        }
        else
        {
            reader.Close();
            lblError.Text = "(no questions found)";
        }
        ViewState["listOfCorrectAnswerIDs"] = listOfCorrectAnswerIDs;

    }
    catch
    {
        lblError.Text = "Database connection error - failed to read records.";
    }
    finally
    {
        conn.Close();
    }
}

    protected void Button3_Click(object sender, EventArgs e)
{
    if (((CheckBoxList)this.FindControl("cblAnswers")) != null)
    {
        List<string> selectedValues = ((CheckBoxList)this.FindControl("cblAnswers")).Items.Cast<ListItem>()
    .Where(li => li.Selected)
    .Select(li => li.Value)
    .ToList();
        for (int i = 0; i < selectedValues.Count; i++)
        {
            lblSelected.Text += selectedValues[i].ToString();
        }
    }
}

【问题讨论】:

    标签: c# asp.net dynamic controls asp.net-controls


    【解决方案1】:

    加载问题时,将使用答案填充的控件的名称存储在 ViewState 中,并在按钮单击事件中检索控件名称并将其传递给 FindControl()。将其结果转换为 CheckBoxList 和 RadioButtonList 的公共基类型,即 ListControl。按钮处理程序可能如下所示:

    protected void Button3_Click(object sender, EventArgs e)
    {
        string controlName = ViewState["answerControlName"];
        ListControl answersControl = (ListControl)this.FindControl(controlName);
        if (answersControl != null)
        {
            List<string> selectedValues = answersControl.Items.Cast<ListItem>()
                .Where(li => li.Selected)
                .Select(li => li.Value)
                .ToList();
    
            List<string> listOfCorrectAnswerIDs = (List<string>)ViewState["listOfCorrectAnswerIDs"];
    
            // check for equivalency
            string selectedString = string.Join(",", selectedValues.OrderBy(val => val));
            string correctString = string.Join(",", listOfCorrectAnswerIDs.OrderBy(val => val));
    
            bool allAnswersCorrect = selectedString == correctString;
        }
    }
    

    您没有指定如何比较答案集,所以在这里我提供了一种简单的方法来检查这些集是否相等(对值进行排序,转换为逗号-分隔列表,并使用字符串相等)。如果您想要 % correct 之类的内容,最好循环遍历正确答案并检查每个答案以查看它是否包含在 selectedValues 列表中,或者使用 LINQ 集合操作函数(如 .Intersect())。

    【讨论】:

      【解决方案2】:

      这是因为您动态创建这些控件的方式。您是在页面初始化所有控件之后创建它们,因此您在每个 PostBack 上都会丢失它们。我建议阅读ASP.NET Page Life Cycle

      您有多种选择来实现您的目标。您可以覆盖CreateChildControls 方法,或覆盖页面的OnInit 方法。两者都可以完成同样的事情,但如果使用后者,请记住调用基本的 Init 方法。

      protected override void CreateChildControls()
      {
          CreateDynamicControls();
      }
      
      protected override void OnInit(EventArgs e)
      {
          CreateDynamicControls();
          base.OnInit(e);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-21
        • 1970-01-01
        • 2012-06-16
        相关资源
        最近更新 更多