乍一看,我要检查两件事。首先,确保您正在实施IPostBackDataHandler
. 这需要您实现两种方法,LoadPostData
并且RaisePostDataChangedEvent
. 在我的第一个猜测中,第一个可能是您问题的根源。
手动处理回发
LoadPostData
接受一个字符串postDataKey
和 a并返回一个指示值是否由于回发而改变的值。您不需要按照.Net 最初打算的方式实现这一点,例如,我创建了一个包含多个单选按钮的控件(由于此处不重要的原因,不能简单地成为控件),因此确保它们是全部由一个属性命名并检查:NameValueCollection
postCollection
bool
RadioButtonList
string 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)
手动处理视图状态
如果手动处理回发不能解决您的问题,则可能是您需要弄乱控件的视图状态。别担心,只要您遵循一些简单的规则,这远没有看起来那么可怕。
要手动处理您的视图状态,您只需要重写两个调用的方法,显然足够了,LoadViewState
并且SaveViewState
. 第一个需要一个object
视图状态来膨胀,另一个返回相同的object
结构。如果你让你的SaveViewState
覆盖返回包含你需要保存所有需要持久的重要属性的结构的东西,那么你只需在你的LoadViewState
方法中再次膨胀它。
这是第一个狡猾的技巧出现的地方。您应该使用某些数据类型来保存视图状态,并且您永远不应该使用任何其他类型(因为其他类型的存储效率非常低)。可能对您最有用的类型是System.Web.UI.Pair
,System.Web.UI.Triplet
以及我们的老朋友System.Collections.ArrayList
和System.Collections.Hashtable
。Pairs 和 Triplets 只存储两个或三个 type 值object
;ArrayLists 实际上是一个List<object>
.
我猜想,在您的情况下,您可能希望存储(1)布尔标志的 ArrayList,存储单选按钮的“检查性”或(2)字符串或整数的 ArrayList,存储 ID 或索引选中的单选按钮。
在我之前提到的控件中,我只需要存储检查和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);
}
同样,如果这在第一次不起作用,您几乎肯定想要单步执行代码或将东西扔到 Trace 中。重要的是,您可能希望避免从这些方法中抛出异常,以防您的视图状态损坏或不存在或其他情况。
进一步阅读视图状态
当我弄乱视图状态时,我会为一些非常有用的文章添加书签。第一个解释了为什么您应该只在视图状态中存储某些类型(例如使用ArrayList
and Hashtable
,而不是List<T>
and Dictionary<TKey, TValue>
),第二个很好地深入解释了所有这些视图状态的实际工作原理。
- 不要让 BinaryFormatter 得到它!
- 真正理解 ViewState
我希望所有这些都有助于解决您的问题。