2010-07-09 14 views
7

मैंने एक कस्टम नियंत्रण विकसित किया है जो ListBox को बढ़ाता है। विचार यह है कि नियंत्रण अपने तत्वों में 'याद करता है' संशोधन जो क्लाइंट-साइड हुआ, उदा। एक AJAX अनुरोध के परिणामस्वरूप।एएसपी.नेट कस्टम नियंत्रण: लोडपोस्टडाटा() कब कहा जाता है?

जिस तरह से यह काम करता है वह यह है कि नियंत्रण एक छिपी हुई इनपुट भी प्रस्तुत करता है, और AJAX अनुरोध का परिणाम छुपा इनपुट में संग्रहीत होता है। यह वापस पोस्ट किया गया है, और नियंत्रण की LoadPostData() विधि छिपी हुई इनपुट की तलाश करती है, और यदि छिपे हुए इनपुट में डेटा है, तो इससे ListItem संग्रह बनाता है।

यह इतने लंबे समय के रूप में उपयोगकर्ता सूची बॉक्स से चयन किया गया है पूरी तरह से काम करता है। यदि वे नहीं हैं, तो LoadPostData() विधि को कॉल नहीं किया जाता है, और इसके परिणामस्वरूप नया ListItem संग्रह नहीं बनाया जाता है। (मैंने डीबगर का उपयोग करके इसे स्थापित किया है।)

मुझे लगता है कि लोडपोस्टडाटा विधि केवल तभी कॉल की जाती है जब POST डेटा संग्रह में नियंत्रण के अद्वितीय आईडी (यानी 'नाम' HTML में विशेषता) शामिल डेटा शामिल होता है। यदि उपयोगकर्ता ने सूची बॉक्स से कोई चयन नहीं किया है, तो सूची बॉक्स के अनन्य आईडी और लोडपोस्टडाटा() के लिए पोस्ट डेटा में कुछ भी शामिल नहीं है। क्या वो सही है?

क्या कोई सुझाव दे सकता है कि मैं यह सुनिश्चित कर सकता हूं कि मेरी कस्टम लिस्टबॉक्स की लोडपोस्टडाटा() विधि को प्रत्येक पोस्टबैक कहा जाता है चाहे उपयोगकर्ता ने चयन किया हो या नहीं?

अग्रिम धन्यवाद - मैं वास्तव में इस के साथ अटक गया हूं।

डेविड

उत्तर

1

मैंने स्थापित किया है कि लोडपॉस्टडाटा() विधि तब तक नहीं बुलाया जाता है जब तक कि पोस्ट डेटा में नियंत्रण के अद्वितीय नाम के समान नाम वाला कोई आइटम न हो। [संपादित करें: पृष्ठ कॉल करना। रजिस्ट्रार आवश्यकताएँ इनिट() के दौरान पोस्टबैक इस पर विजय प्राप्त करता है।] मैं देख सकता हूं क्यों, लेकिन यह काफी सीमित है।

मैंने लोडपोस्टडाटा() विधि के दौरान इसे संभालने से समस्या को दूर नहीं किया है। इसके बजाए, मैंने इसे एक विधि में संभाला है जिसे मैं ऑनलोड() में कॉल करता हूं।

1) अब आप postCollection NameValueCollection वस्तु जो एक तर्क के रूप LoadPostData() विधि में पारित हो जाता है के लिए उपयोग किया:

दो बातें जब इस दृष्टिकोण का उपयोग कर ध्यान में रखा जाना करने की जरूरत है। इसका मतलब है कि आपको Request.Form संग्रह से पोस्ट डेटा निकालना होगा, जो थोड़ा कठिन काम है। 2) चूंकि ऑनलोड() व्यूस्टेट प्रोसेसिंग कोड के बाद होता है, इसलिए आपको ListItems बनाने के बाद मैन्युअल रूप से चयनित वैल्यू सेट करना होगा। यदि आप नहीं करते हैं, तो सूचीबॉक्स AJAX के माध्यम से पॉप्युलेट किया गया है और उपयोगकर्ता चयन करता है, तो चयन खो जाएगा।

मुझे उम्मीद है कि यह भविष्य में किसी की मदद करेगा।

3

काम करने पर ही एक आइटम का चयन किया गया है वास्तव में अजीब लग रहा है। यह जांचने का एक त्वरित तरीका है कि क्या लोडपोस्टडाटा का आह्वान किया जा रहा है, ट्रेसिंग को सक्षम करने और आईपीओस्टबैकडाटाहैंडलर में लोड करना होगा। लोडपोस्टडाटा (...)।

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> 

जब आप आगे बढ़ते हैं, तो आपको ट्रेस में "लोडपोस्टडाटा" देखना चाहिए।

+0

यह बिल्कुल भी अजीब यह काम करता है कि केवल जब एक आइटम का चयन किया जाता है। LoadPostData() विधि केवल तभी कॉल की जाती है जब पोस्टडाटा में एक ही नाम वाला एक आइटम होता है जो नियंत्रण के अद्वितीय आईडी के रूप में होता है - जो तब नहीं होगा जब उपयोगकर्ता ने कोई आइटम नहीं चुना हो। – David

+0

वैसे मेरी पहली प्रतिक्रिया यह थी कि जब मैंने इसे लिखना शुरू किया तो यह अजीब लगा! :) क्या आपने रेंडरकंट्स में डमी फ़ील्ड जोड़ने का प्रयास किया था? इस तरह LoadPostData हमेशा कॉल किया जाएगा। –

+0

नियंत्रण के अद्वितीय आईडी के समान नाम विशेषता वाले 'नकली' तत्व बनाने के बारे में आपके सुझाव के लिए धन्यवाद। मैं देखता हूं कि आपका क्या मतलब है। मेरे दिमाग में यह उतना ही साफ नहीं है जितना मैंने पेश किया है। तुम क्या सोचते हो? – David

8

मैं सिर्फ भविष्य में संदर्भ के लिए इस पर में एक छोटे से देर से कूद हूँ, लेकिन, यहाँ है कि कैसे मैं कुछ इसी तरह ...

मेरे नियंत्रण एक पेड़ नोड्स के लिए टेम्पलेट्स का उपयोग करता है पूरा किया। जिस मुद्दे पर मैं इससे निपट रहा था वह क्लाइंट पक्ष को नोड्स के विस्तारित/ध्वस्त राज्य में बदलने के तरीके को कैप्चर करना था। काम खत्म हो गया था:

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]; 
    ... 
} 

वर्गों के भीतर व्यक्तिगत नोड्स के लिए मेरे पास कोड है जो मेरे टॉगल बटन की ऑनक्लिक घटनाओं को एक जावास्क्रिप्ट फ़ंक्शन पर कॉल के साथ पॉप्युलेट करता है जो बेस कंट्रोल की आईडी लेता है और व्यक्तिगत नोड्स को तर्क के रूप में लेता है दस्तावेजों।

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"); 
... 
} 

जावास्क्रिप्ट तो के रूप में घटना होने वाले के लिए आवश्यक छिपा फ़ील्ड का मान संशोधित करता है। जब हम सर्वर पर वापस आते हैं तो मैं इस क्षेत्र की सामग्री को पार्स करने में सक्षम हूं और इसे फिर से प्रस्तुत करने से पहले नियंत्रण स्थिति को संशोधित कर सकता हूं। (नोट: मैं वास्तव में अलग घटनाओं पर नज़र रखने के लिए 3 छिपा क्षेत्रों का उपयोग लेकिन अवधारणा ही है)

आशा इस भविष्य में दूसरों में मदद करता है ...

+0

आपके योगदान के लिए धन्यवाद। – David

+3

ऑनइनिट वही था जो यहां गायब था - धन्यवाद! – dividius

संबंधित मुद्दे