Asp.net

ASP.NET 自定義控制項:何時呼叫 LoadPostData()?

  • February 25, 2011

我開發了一個擴展 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”。

引用自:https://stackoverflow.com/questions/3211200