制定MSQ响应收集

时间:2013-05-06 10:04:48

标签: c# dictionary radio-button checkbox

长话短说,我正在做一个考试申请,作为我实习的一部分。我目前在候选控制台模块上,该模块负责显示每个部分的问题并收集回复。响应收集基于提供的问题类型。如果问题是多项选择,候选控制台将使用(自定义)单选按钮的组框显示它。例如 - :

MCQ Response

如果问题是多选,则候选控制台使用(自定义)复选框的组框显示它。例如 - :

MSQ Response

我已经能够在IRC的帮助下成功实施MCQ响应收集。但是,遵循相同的逻辑,我在实施MSQ响应收集方面遇到了绊脚石。

//This is in the QuestionDisplay class.
//MCQ
public void AddOption_mcq(string optionText, bool arg, int QNo, int option)
{
     CustomRadio rb = new CustomRadio();
     rb.Text = optionText;
     rb.Location = new Point(3, 40 + grbOptions.Controls.Count * 30);
     rb.AutoSize = true;
     rb.Checked = arg;
     rb.QuestionNumber = QNo;
     rb.optionId = option;
     rb.CheckedChanged += delegate(Object sender, System.EventArgs e)
     {
           temp = sender as CustomRadio;
           if (!ResponseMCQ.ContainsKey(QNo)) //First time question is marked, ResponseMCQ is a <int,ButtonBase> dict.
           {
                ResponseMCQ.Add(QNo, temp);
           }
           else
                ResponseMCQ[QNo] = temp; //All other times
     };
     grbOptions.Controls.Add(rb); //grbOptions is a groupbox control.
}

//MSQ
public void AddOption_msq(string optionText, bool arg, int QNo, int option)
{
     CustomChecks cb = new CustomChecks();
     cb.Text = optionText;
     cb.Location = new Point(3, 40 + grbOptions.Controls.Count * 30);
     cb.AutoSize = true;
     cb.Checked = arg;
     cb.QuestionNumber = QNo;
     cb.optionId = option;
     cb.CheckedChanged += delegate(Object sender, System.EventArgs e)
     {
          temp = sender as CustomChecks;
          if(MSQs.Any())
              foreach (CustomChecks C in MSQs) //Clear elements from List if on a different question
              {
                   if (C.QuestionNumber != ((CustomChecks)temp).QuestionNumber)
                   {
                       IsDifferent = true;
                       break;
                   }
              }
          if (IsDifferent == true)
          {
               MSQs.Clear();
               IsDifferent = false;
          }
          if(!MSQs.Any(x => x.Text.Equals(optionText))) //Check if the checkbox already exists in the List
               MSQs.Add(temp);
          if (!ResponseMSQ.ContainsKey(QNo)) //First time the question is marked
          {
               ResponseMSQ.Add(QNo, MSQs);
          }
          else
               ResponseMSQ[QNo] = MSQs; //All other times
    };
    grbOptions.Controls.Add(cb);
    if (MSQs.Any())
    {
          foreach (CustomChecks C in MSQs)
          {
               foreach (CustomChecks D in grbOptions.Controls)
               {
                    if (D.Text.Equals(C.Text))
                    {
                        D.Checked = C.Checked;
                    }
               }
          }
    }
}

//In the main project, this is how I collect MCQ responses -:
temp = questionDisplay1.GetResponse; //questionDisplay1 is a QuestionDisplay object and GetResponse is a ButtonBase object, used to temporarily store the clicked radio button(CustomRadio object).
//MCQResponse is a Dictionary<int, ButtonBase> which stores <QuestionNumber, CustomRadio>.
if (QuesTypes[i].Equals("MCQ"))
{
         if (questionDisplay1.MCQResponse.TryGetValue(i, out temp) && questionDisplay1.MCQResponse[i].Text.Equals(s))
         {
               questionDisplay1.AddOption_mcq(s, true, i, optionId);
         }
         else
               questionDisplay1.AddOption_mcq(s, false, i, optionId);
}

MCQResponseMSQResponse分别属于Dictionary<int, ButtonBase>Dictionary<int, List<ButtonBase>>类型。它们根据QuestionNumber:Object mapping存储数据,其中Object可以是CustomRadioCustomChecks

对于MCQ,我使用临时ButtonBase对象temp来存储CustomRadio对象(CheckedChanged事件)。这是第一次标记问题,检查字典。如果不存在,则添加该条目。对于所有其他时间,只需编辑条目。

现在对于MSQ来说,我正试图遵循类似的逻辑,但我正在搞砸某个地方。我使用临时List对象MSQs来存储多个CustomChecks响应。在第一个if的情况下,如果我遇到一个与我单击复选框的问题不同的问题,我会清除列表。接下来,我检查列表中是否已存在该复选框。如果不存在,我添加它。最后,我使用与MCQ响应集合中类似的逻辑。

为了正确显示CustomChecks元素,添加了最后的foreach循环。我应该为此目的使用MSQResponse,但我无法弄清楚如何。以下是我面临的主要问题 - :

  • 仅针对一个问题持久显示MSQ响应。如果我在另一个问题中选中复选框,则不会显示之前的复选框。我必须在主项目中构建类似于我为MCQ做的代码,并且无法为此目的弄清楚。
  • 使用MSQResponse。我没有正确使用它。必须有一种更有效的方法来使用此词典收集MSQ响应。
  • MSQ方法结束时的双foreach循环非常昂贵。我听说过.NET 4中的Zip操作,但是我的项目负责人在严格的指令下使用.NET 3.5。它仅用于持久显示,但仅适用于一个问题。如果我可以完全取消它,我会很高兴。

任何帮助将不胜感激!


修改

所以,我尝试了James Holderness给出的方法。代码如下 - :

public void AddOption_msq(string optionText, bool arg, int QNo, int option)
{
        CustomChecks cb = new CustomChecks();
        cb.Text = optionText;
        cb.Location = new Point(3, 40 + grbOptions.Controls.Count * 30);
        cb.AutoSize = true;
        cb.Checked = arg;
        cb.QuestionNumber = QNo;
        cb.optionId = option;

        cb.CheckedChanged += delegate(Object sender, System.EventArgs e)
        {
            temp = sender as CustomChecks;
            if (!ResponseMSQ.ContainsKey(QNo))
            {
                // First time, add an empty list
                ResponseMSQ.Add(QNo, new List<ButtonBase>());
            } 
            if (!ResponseMSQ[QNo].Any(x => x.Text.Equals(optionText))) //Check if the checkbox already exists in the List
            {
                ResponseMSQ[QNo].Add(temp);
            }
            if (((CustomChecks)temp).Checked == false) //Removing the checkbox if deselected
            {
                foreach (CustomChecks C in ResponseMSQ[QNo])
                    if (C.Text.Equals(temp.Text))
                    {
                        ResponseMSQ[QNo].Remove(C);
                        break;
                    }

            }
        };
        grbOptions.Controls.Add(cb);
        if (ResponseMSQ.ContainsKey(QNo) && ResponseMSQ[QNo].Any()) //For persistently displaying the proper checked state.
        {
            foreach (CustomChecks C in ResponseMSQ[QNo])
            {
                foreach (CustomChecks D in grbOptions.Controls)
                {
                    if (D.Text.Equals(C.Text))
                    {
                        D.Checked = C.Checked;
                    }
                }
            }
        }
}

这很有效。我调试了以检查 - :

  1. 正在存储响应:ResponseMSQ正在根据需要存储它们。
  2. 根据需要显示复选框:由于最后加倍foreach,复选框的状态正在正确显示。
  3. 现在剩下的唯一问题是关于双foreach的运行时间,但这个解决方案有效。如果有人知道比一次迭代两个列表更好的方法,他们可以在评论中发布它。再次感谢!

1 个答案:

答案 0 :(得分:1)

我的C#/ .NET有点生疏,但是你的MSQ CheckedChanged委托会不会更容易做这样的事情:

temp = sender as CustomChecks;
if (!ResponseMSQ.ContainsKey(QNo)) 
{                             
    // First time, add an empty list
    ResponseMSQ.Add(QNo, new List<ButtonBase>());
} 
// At this point you're guaranteed there's something in the dictionary
// for your QNo, even if it's just an empty list.                                    
if (!ResponseMSQ[QNo].Any(x => x.Text.Equals(optionText)))
{
    // If the checkbox isn't already in the list, then add it
    ResponseMSQ[QNo].Add(temp); 
}

在MCQ和MSQ案例中,您永远不会从这些词典中删除任何内容。某人是否永远不可能改变他们的回应?