C# Asp复合控件子控件(单选按钮)丢失选中值
我正在asp.net中使用动态创建的问题和选项开发测验控件。 主控件基本上是一个容纳所有问题的容器。 在“设计”视图中,用户可以通过自定义集合编辑器添加问题。 每次我向集合编辑器列表添加问题时,它都会为我生成一个问题标签。 每个问题对象内部都有一个标签和n个继承Radiobutton控件的选项对象。每个选项对象依次表示用户可以为每个问题选择的选项 这一切工作,除了我现在的部分,我希望能够读取每个单选按钮的检查值。当我想在页面内实施此测验并检查问题时,我想在此页面中放置一个按钮并调用控件内的以下函数: $ 但是,一旦我选择一个单选按钮并单击submit按钮,所有选项的选中值都将变为false。 基本上,它在回发后失去了它的校验值,我只是被困在试图解决它。C# Asp复合控件子控件(单选按钮)丢失选中值,c#,asp.net,composite-controls,C#,Asp.net,Composite Controls,我正在asp.net中使用动态创建的问题和选项开发测验控件。 主控件基本上是一个容纳所有问题的容器。 在“设计”视图中,用户可以通过自定义集合编辑器添加问题。 每次我向集合编辑器列表添加问题时,它都会为我生成一个问题标签。 每个问题对象内部都有一个标签和n个继承Radiobutton控件的选项对象。每个选项对象依次表示用户可以为每个问题选择的选项 这一切工作,除了我现在的部分,我希望能够读取每个单选按钮的检查值。当我想在页面内实施此测验并检查问题时,我想在此页面中放置一个按钮并调用控件内的以下函
如果有人能为我指出正确的方向,我将不胜感激。乍一看,有两件事我要检查一下。首先,确保您正在实施。这需要实现两种方法,
LoadPostData
和RaisePostDataChangedEvent
。我的第一个猜测是,第一个可能是你问题的根源
手动处理回发
LoadPostData
获取一个字符串postDataKey
和一个postCollection
,并返回一个bool
,指示值是否因回发而改变。您不需要按照.Net最初的意图来实现它,例如,我创建了一个包含多个单选按钮的控件(出于此处不重要的原因,它不能只是一个RadioButtonList
控件)因此,请确保它们都是由属性字符串GroupName
命名的,并检查postCollection
中的GroupName
:
public bool LoadPostData(string postDataKey,
System.Collections.Specialized.NameValueCollection postCollection)
{
bool oldValue = _isChecked;
postCollection = HttpContext.Current.Request.Form; // See note below
_isChecked = (postCollection[this.GroupName] == this.Text);
return oldValue == _isChecked;
}
你会注意到我在这里重新定义了postCollection
;这是因为postCollection
只包含HttpRequest.Form
的子集,对应于ASP.Net认为控件应该关心的内容。当您在这里构建复合控件时,您可能也希望这样做
如果这在第一次不起作用,不要担心;在调试模式下(或者将内容输出到HttpContext.Trace
,我经常发现这更容易)单步了解一下为什么您的代码不是您所需要的
快速警告
最后一件事:LoadPostData
仅在发布表单包含名称与控件的UniqueID
匹配的字段时调用。由于您的控件是复合控件,您可能希望稍微简化此操作,如下所示:
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
writer.WriteBeginTag("input");
writer.WriteAttribute("type", "hidden");
writer.WriteAttribute("name", this.UniqueID);
writer.WriteAttribute("value", "post");
writer.Write(" />");
}
这是一个肮脏的黑客,但它会工作;o)
手动处理viewstate
如果手动处理回发无法解决您的问题,则可能需要处理控件的viewstate。别担心,只要你遵循一些简单的规则,这远没有看上去那么可怕
要手动处理viewstate,您只需覆盖两个方法,显然,这两个方法分别是LoadViewState
和SaveViewState
。第一个将viewstate的对象
充气,另一个返回相同的对象
结构。如果使SaveViewState
覆盖返回包含保存所有需要持久化的重要属性所需结构的内容,则只需在LoadViewState
方法中再次充气即可
这里是第一个狡猾的把戏出现的地方。保存viewstate时应该使用某些数据类型,并且永远不要使用任何其他类型(因为其他类型的存储效率非常低)。可能对你最有用的类型是,以及我们的老朋友和朋友。成对和三元组只存储两个或三个类型为object
的值;ArrayList实际上是一个列表
我猜,在您的环境中,您可能想要存储(1)布尔标志的ArrayList,存储单选按钮的“检查性”;或者(2)字符串或整数的ArrayList,存储选中单选按钮的ID或索引
在我前面提到的控件中,我只需要存储checkedness和Text
属性,因此我的LoadViewState
和SaveViewState
方法如下所示:
protected override void LoadViewState(object savedState)
{
Pair state = savedState as Pair;
if (state != null)
{
_isChecked = state.First as Nullable<bool> ?? false;
this.Text = state.Second as string;
}
}
protected override object SaveViewState()
{
return new Pair(_isChecked, this.Text);
}
protected override void LoadViewState(对象保存状态)
{
Pair state=将数据状态保存为Pair;
如果(状态!=null)
{
_isChecked=状态。首先为可空??false;
this.Text=state.Second作为字符串;
}
}
受保护的覆盖对象SaveViewState()
{
返回新的对(_已选中,this.Text);
}
同样,如果这在第一次不起作用,您几乎肯定希望逐步完成代码或将内容放入跟踪中。重要的是,您可能希望避免从这些方法引发异常,以防viewstate损坏或不存在或其他情况
进一步阅读viewstate
当我在处理viewstate时,有几篇非常有用的文章会被我保留在书签中。第一个解释了为什么应该只在viewstate中存储某些类型(比如使用ArrayList
和Hashtable
,而不是List
和Dictionary
),第二个解释了所有viewstate内容的实际工作原理
我希望所有这些都有助于解决您的问题。非常感谢您的详细解释,写得非常好!是的,我在和viewstate的
protected override void LoadViewState(object savedState)
{
Pair state = savedState as Pair;
if (state != null)
{
_isChecked = state.First as Nullable<bool> ?? false;
this.Text = state.Second as string;
}
}
protected override object SaveViewState()
{
return new Pair(_isChecked, this.Text);
}