考试试卷实现思路与自定义控件的问题
大家好,请教一个关于自定义控件的问题,把问题描述清楚,篇幅比较长,请大家耐心查看。
正在做在线考试的功能,需求如下:
预览试卷:
图1
考试试卷:
图2
查看答卷:
图3
要做到以上的功能,我的思路是这样的:
1.问题(题目和选项)的显示,是最基本的,以上3个情况都包括了,因此把它们独立出来。
2.考试试卷,需要在选项旁边加入验证控件。查看答卷,需要在选项下面加入一段内容。总的来说,是在选项旁边加“东西”。
实现情况:
1.问题类型(预览试卷、考试试卷、查看答卷的问题),Question。题目(预览试卷、考试试卷、查看答卷的问题)类型,Subject。选项(预览试卷、考试试卷、查看答卷的选项)类型,Option。这3个概念,已经抽象并独立了。问题包含题目和选项。
2.需要加的内容,叫Decorator。
3.接着,是在考试试卷的选项旁边,加上验证控件。现在报错如下:
具体实现:
1.类图:
2.Question : CompositeControl
// 问题
internal abstract class Question : CompositeControl
{
internal Question(SubjectControl subjectControl, OptionControl optionControl)
{
this.subjectControl = subjectControl;
this.optionControl = optionControl;
}
#region 构建容器界面
protected override void CreateChildControls()
{
this.Controls.Clear();
// 问题内容
this.phSubject = new PlaceHolder();
this.phSubject.ID = "phSubject";
this.phSubject.Controls.Add(this.CreateSubject(this._pqInfo.QuestionInfo.Content));
this.Controls.Add(this.phSubject);
// 选项
this.phOption = new PlaceHolder();
this.phOption.ID = "phOption";
this.phOption.Controls.Add(this.optionControl);
this.Controls.Add(phOption);
this.ChildControlsCreated = true;
}
protected override void Render(HtmlTextWriter writer)
{
this.RenderSubject(writer);
this.RenderOption(writer);
}
protected virtual void RenderSubject(HtmlTextWriter writer)
{
#region 题目
#region Tr
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tdbg"); // Begin Tr
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
#region Td
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tdQuestion"); // Begin Td
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
hdnPaperQuestionID.RenderControl(writer);
hdnCategoryID.RenderControl(writer);
ltrID.RenderControl(writer);
phSubject.RenderControl(writer);
writer.RenderEndTag(); // End Td
#endregion
writer.RenderEndTag(); // End Tr
#endregion
#endregion
}
protected virtual void RenderOption(HtmlTextWriter writer)
{
#region 选项
#region Tr
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tdbg"); // Begin Tr
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
#region Td
writer.AddAttribute(HtmlTextWriterAttribute.Class, "tdOption"); // Begin Td
writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
writer.RenderBeginTag(HtmlTextWriterTag.Td);
phOption.RenderControl(writer);
writer.RenderEndTag(); // End Td
#endregion
writer.RenderEndTag(); // End Tr
#endregion
#endregion
}
#endregion
}
// 考试问题
internal class ExamQuestion : Question
{
internal ExamQuestion(SubjectControl subjectControl, OptionControl optionControl)
: base(subjectControl, optionControl)
{
}
protected override void CreateChildControls()
{
base.CreateChildControls();
// 附加内容
this.phDecorator = new PlaceHolder();
this.phDecorator.ID = "phDecorator";
OptionDecoratorContext odContext = new OptionDecoratorContext();
OptionDecorator optionDecorator = odContext.GetOptionDecorator(this.PaperCategory, this.PqInfo.QuestionInfo.CategoryID);
this.OptionDecorator = optionDecorator;
optionDecorator.OptionControl = this.OptionControl;
this.phDecorator.Controls.Add(optionDecorator);
this.Controls.Add(phDecorator);
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
#region 附加功能
writer.RenderBeginTag(HtmlTextWriterTag.Tr);
writer.RenderBeginTag(HtmlTextWriterTag.Td);
this.OptionDecorator.BeValidateControlClientID = this.OptionControl.Option.ClientID;
this.OptionDecorator.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
#endregion
}
}
// 选项
internal abstract class OptionControl : CompositeControl
{
protected override void CreateChildControls()
{
this.Controls.Clear();
this._option = this.CreateOptionControl(this._qInfo);
this.Controls.Add(this._option);
this.ChildControlsCreated = true;
}
protected override void Render(HtmlTextWriter writer)
{
this._option.RenderControl(writer);
}
// 单选选项
internal class PaperSingleOption : OptionControl
{
/// <summary>
/// 构建考试题目的选项控件
/// </summary>
/// <param name="qInfo">题目试题</param>
/// <returns>ASP.NET服务器控件</returns>
internal override Control CreateOptionControl(QuestionInfo qInfo)
{
RadioButtonList _rblSingleChoice = new RadioButtonList();
_rblSingleChoice.ID = "rblSingleChoice";
_rblSingleChoice.Items.AddRange(this.ToListItem(qInfo.Option));
_rblSingleChoice.RepeatDirection = RepeatDirection.Horizontal;
return _rblSingleChoice;
}
// 选项的附加功能
internal abstract class OptionDecorator : CompositeControl
{
protected override void CreateChildControls()
{
this.Controls.Clear();
this._decorator = this.CreateOptionDecorator();
this.Controls.Add(this._decorator);
this.ChildControlsCreated = true;
}
protected override void Render(HtmlTextWriter writer)
{
this._decorator.RenderControl(writer);
}