这是我最喜欢的把戏:)
我们的场景是首先渲染一个控件。然后使用来自用户的一些输入,呈现更多控件并让它们响应事件。
这里的关键是状态——你需要知道控件到达 PostBack 时的状态——所以我们使用 ViewState。那么问题就变成了先有鸡还是先有蛋的问题。ViewState 在调用之后才可用LoadViewState()
,但您必须在调用之前创建控件才能正确触发事件。
诀窍是覆盖LoadViewState()
,SaveViewState()
因此我们可以控制事物。
(请注意,下面的代码是粗略的,来自记忆,可能有问题)
private string searchQuery = null;
private void SearchButton(object sender, EventArgs e)
{
searchQuery = searchBox.Text;
var results = DataLayer.PerformSearch(searchQuery);
CreateLinkButtonControls(results);
}
// We save both the base state object, plus our query string. Everything here must be serializable.
protected override object SaveViewState()
{
object baseState = base.SaveViewState();
return new object[] { baseState, searchQuery };
}
// The parameter to this method is the exact object we returned from SaveViewState().
protected override void LoadViewState(object savedState)
{
object[] stateArray = (object[])savedState;
searchQuery = stateArray[1] as string;
// Re-run the query
var results = DataLayer.PerformSearch(searchQuery);
// Re-create the exact same control tree as at the point of SaveViewState above. It must be the same otherwise things will break.
CreateLinkButtonControls(results);
// Very important - load the rest of the ViewState, including our controls above.
base.LoadViewState(stateArray[0]);
}