ASP.NET 自定義控制項:何時呼叫 LoadPostData()?
我開發了一個擴展 ListBox 的自定義控制項。這個想法是控制項“記住”在客戶端發生的對其元素的修改,例如作為 AJAX 請求的結果。
它的工作方式是該控制項還呈現隱藏輸入,AJAX 請求的結果儲存在隱藏輸入中。這被回發,控制項的 LoadPostData() 方法查找隱藏的輸入,如果隱藏的輸入有數據,則從它創建 ListItem 集合。
***只要使用者從列錶框中進行了選擇,***它就可以完美地工作。如果沒有,則不會呼叫 LoadPostData() 方法,因此不會創建新的 ListItem 集合。(我已經使用調試器建立了這個。)
我假設只有當 POST 數據集合包含與控制項的 UniqueID(即 HTML 中的“名稱”屬性)相對應的數據時,才會呼叫 LoadPostData 方法。如果使用者尚未從列錶框中進行選擇,則列錶框的 UniqueID 的發布數據中不會包含任何內容,並且不會呼叫 LoadPostData()。那是對的嗎?
任何人都可以建議我如何確保每次回發都呼叫我的自定義 ListBox 的 LoadPostData() 方法,而不管使用者是否進行了選擇?
在此先感謝-我真的很喜歡這個。
大衛
我在這方面有點晚了,但是,為了將來參考,這裡是我如何完成類似的事情……
我的控制項是使用節點模板的樹。我正在處理的問題是如何擷取客戶端對節點展開/折疊狀態的更改。最終起作用的是:
在 CreateChildControls 中,將隱藏欄位添加到我的根控制項的控制項集合中。
protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding) { ... _cdExpanded = new HiddenField(); _cdExpanded.ID = "cdExpanded"; this.Controls.Add(_cdExpanded); ... }在 OnInit 呼叫中
protected override void OnInit(EventArgs e) { ... Page.RegisterRequiresPostBack(this); ... }在 LoadPostData 中查找與隱藏欄位的 UniqueID(不是 ClientID)匹配的文章集合中的值:
public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { ... string cdExpanded = postCollection[_cdExpanded.UniqueID]; ... }在各個節點的類中,我有程式碼通過呼叫 JavaScript 函式來填充切換按鈕的 onclick 事件,該函式將基本控制項的 ID 和各個節點作為參數。
string ToggleScript { get { return "ToggleNode('" + this.ClientID + "', '" + _TreeRoot.ClientID + "');"; } } protected override void Render(HtmlTextWriter writer) { ... if (this.HasChildren) { writer.AddAttribute("onclick", ToggleScript); } ... }這使得通過 getElementById 找到隱藏欄位相當容易:
function ToggleNode(nodeID, treeID) { var cdExpanded = document.getElementById(treeID + "_cdExpanded"); ... }JavaScript 然後根據發生事件的需要修改隱藏欄位的值。當我們回到伺服器時,我能夠解析出該欄位的內容並根據需要修改控制項狀態,然後再重新渲染。(注意:我實際上使用 3 個隱藏欄位來跟踪不同的事件,但概念是相同的)
希望這對將來的其他人有所幫助……
僅在選擇項目時才工作聽起來真的很奇怪。檢查是否正在呼叫 LoadPostData 的一種快速方法是啟用跟踪並將以下內容放入 IPostBackDataHandler.LoadPostData(…)。
Page.Trace.Write("My control", "LoadPostData");如果是這種情況,您應該確保您擁有以下內容:
Page.RegisterRequiresPostBack(this) in OnInit這是一個完整的範例控制項。
using System; using System.Collections.Generic; using System.Text; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel.Design; using System.ComponentModel; using System.Web.UI.Design; namespace Controls { public sealed class ExtendedListBoxDesigner : ControlDesigner { public override string GetDesignTimeHtml() { StringBuilder sb = new StringBuilder(); sb.Append("<div>My designer</div>"); return sb.ToString(); } } [DesignerAttribute(typeof(ExtendedListBoxDesigner), typeof(IDesigner))] public class ExtendedListBox : ListBox, INamingContainer, IPostBackDataHandler { bool IPostBackDataHandler.LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { Page.Trace.Write("ExtendedListBox", "LoadPostData"); return true; } protected override void OnInit(EventArgs e) { Page.RegisterRequiresPostBack(this); base.OnInit(e); } protected override void RenderContents(HtmlTextWriter writer) { base.RenderContents(writer); writer.Write(string.Format("<input type=\"hidden\" name=\"{0}_dummy\" value=\"alwaysPostBack\">", this.ID)); } } }頁面看起來像這樣。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ControlSamlpe._Default" Trace="true" %> <%@ Register Assembly="Controls" Namespace="Controls" TagPrefix="sample" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <sample:ExtendedListBox runat="server" ID="extListBox"></sample:ExtendedListBox> <asp:Button runat="server" ID="go" /> </div> </form> </body> </html>當您點擊 go 時,您應該會在跟踪中看到“LoadPostData”。