2009-08-24 16 views
5

मैं वर्तमान में अपने एप्लिकेशन के एक हिस्से के साथ काम कर रहा हूं जो गतिशील वेब उपयोगकर्ता नियंत्रण का उपयोग करता है और मुझे व्यूस्टेट या किसी अन्य विधि का उपयोग करके पोस्टबैक पर नियंत्रण को पुन: प्रारंभ करने का सबसे अच्छा तरीका पता लगाने में कुछ परेशानी हो रही है मुझे प्रत्येक पोस्टबैक पर डेटाबेस से पूछने की आवश्यकता नहीं है।डेटाबेस का उपयोग किये बिना गतिशील एएसपी.NET उपयोगकर्ता नियंत्रण को मैं फिर से चालू कैसे कर सकता हूं?

असल में मेरे पृष्ठ पर जो कुछ है वह एक उपयोगकर्ता नियंत्रण है जिसमें बाल उपयोगकर्ता नियंत्रण की एक परिवर्तनीय मात्रा रखने के लिए एक पैनल होता है और एक बटन जो "नियंत्रण जोड़ें" कहता है जिसका कार्य सुंदर आत्म व्याख्यात्मक है।

बाल उपयोगकर्ता नियंत्रण बहुत आसान है; यह सिर्फ एक डिलीट बटन है, एक ड्रॉप डाउन है, और एक पंक्ति पिकर नियंत्रण एक पंक्ति में व्यवस्थित है। जब भी उपयोगकर्ता अभिभावक नियंत्रण पर नियंत्रण जोड़ें बटन पर क्लिक करता है, तो बाल नियंत्रण वाले पैनल में एक नई 'पंक्ति' जोड़ दी जाती है।

मैं क्या करना चाहता हूं कि इस संग्रह में नियंत्रण जोड़ने और निकालने, मूल्यों को संशोधित करने और डेटाबेस में किसी भी कॉल किए बिना मुझे 'इन-मेमोरी' करने के लिए जो भी ऑपरेशन करने की आवश्यकता है, उसे करने में सक्षम होना है। जब मैं नियंत्रण जोड़ रहा हूं और उनके मूल्यों को पॉप्युलेट कर रहा हूं, तो मैं नियंत्रण से सभी डेटा को एक ही समय में डेटाबेस से सहेजने/अपडेट करने के लिए "सेव" पर क्लिक करना चाहता हूं। वर्तमान में मुझे मिला एकमात्र समाधान बस प्रत्येक पोस्ट को डेटाबेस में डेटा को सहेजना है और फिर डीबी में संग्रहीत पंक्तियों का उपयोग पोस्टबैक पर नियंत्रण को फिर से चालू करने के लिए करना है। जाहिर है, यह उपयोगकर्ता को उनकी इच्छानुसार डीबी में परिवर्तनों को सहेजने के लिए मजबूर करता है और यदि वे अपने डेटा को सहेजे बिना नियंत्रण के साथ काम करना रद्द करना चाहते हैं, तो यह सुनिश्चित करने के लिए अतिरिक्त काम किया जाना चाहिए कि पहले किए गए पंक्तियां हटा दी गई हैं।

गतिशील नियंत्रणों के उपयोग के बारे में मैंने जो सीखा है, उससे मुझे पता है कि जीवन चक्र के इनिट चरण के दौरान पृष्ठ में नियंत्रण जोड़ना और फिर लोड मान में उनके मूल्यों को पॉप्युलेट करना सबसे अच्छा है। मैंने यह भी सीखा है कि यह सुनिश्चित करने का एकमात्र तरीका है कि आप नियंत्रण के दृष्टिकोण को जारी रख सकते हैं यह सुनिश्चित करना है कि आप प्रत्येक गतिशील नियंत्रण को एक अद्वितीय आईडी दें और नियंत्रण को तुरंत चालू करते समय इसे सटीक आईडी असाइन करना सुनिश्चित करें। मैंने यह भी सीखा है कि व्यूस्टेट वास्तव में जीवन चक्र में इनिट चरण के बाद तक लोड नहीं होता है। यह वह जगह है जहां मेरी समस्या निहित है। यदि मैं व्यूस्टेट का उपयोग करने में असमर्थ हूं और मैं डेटाबेस में कोई कॉल नहीं करना चाहता हूं तो मैं इन नियंत्रणों के नाम कैसे संग्रहीत और पुनर्प्राप्त कर सकता हूं? क्या एएसपीनेट का उपयोग करके मूल्यों की इन-मेमोरी मैनिपुलेशन/बैच की बचत भी संभव है?

किसी भी मदद की बहुत सराहना की है,

माइक

+0

थोड़ा देर हो चुकी है, लेकिन मुझे ऐसा लगता है: http://stackoverflow.com/a/15346332/52898 – Tommy

उत्तर

3

आप क्या आप की जरूरत है की न्यूनतम संग्रहीत कर सकती है सत्र में आयोजित संग्रह में नियंत्रण को फिर से बनाना सीखें। सत्र पृष्ठ के init चरणों के दौरान उपलब्ध है।

यहां आपके लिए एक उदाहरण है। यह के होते हैं:

Default.aspx, सीएस
- उपयोगकर्ता स्टोर करने के लिए पैनल को नियंत्रित करता है
- जो एक उपयोगकर्ता नियंत्रण हर बार

TimeTeller.ascx, सीएस
क्लिक किया जाता है जोड़ देगा "नियंत्रण बटन जोड़ें" - सेटटाइम नामक एक विधि है जो निर्दिष्ट समय पर नियंत्रण पर एक लेबल सेट करती है।

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="DynamicControlTest._Default" %> 

<!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></title> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <asp:Panel ID="pnlDynamicControls" runat="server"> 
     </asp:Panel> 
     <br /> 
     <asp:Button ID="btnAddControl" runat="server" Text="Add User Control" 
      onclick="btnAddControl_Click" /> 
    </div> 
    </form> 
</body> 
</html> 

Default.aspx.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

namespace DynamicControlTest 
{ 
    public partial class _Default : System.Web.UI.Page 
    { 
     Dictionary<string, string> myControlList; // ID, Control ascx path 

     protected void Page_Load(object sender, EventArgs e) 
     { 

     } 

     protected override void OnInit(EventArgs e) 
     { 
     base.OnInit(e); 

     if (!IsPostBack) 
     { 
      myControlList = new Dictionary<string, string>(); 
      Session["myControlList"] = myControlList; 
     } 
     else 
     { 
      myControlList = (Dictionary<string, string>)Session["myControlList"]; 

      foreach (var registeredControlID in myControlList.Keys) 
      { 
       UserControl controlToAdd = new UserControl(); 
       controlToAdd = (UserControl)controlToAdd.LoadControl(myControlList[registeredControlID]); 
       controlToAdd.ID = registeredControlID; 

       pnlDynamicControls.Controls.Add(controlToAdd); 
      } 
     } 
     } 

     protected void btnAddControl_Click(object sender, EventArgs e) 
     { 
     UserControl controlToAdd = new UserControl(); 
     controlToAdd = (UserControl)controlToAdd.LoadControl("TimeTeller.ascx"); 

     // Set a value to prove viewstate is working 
     ((TimeTeller)controlToAdd).SetTime(DateTime.Now); 
     controlToAdd.ID = Guid.NewGuid().ToString(); // does not have to be a guid, just something unique to avoid name collision. 

     pnlDynamicControls.Controls.Add(controlToAdd); 

     myControlList.Add(controlToAdd.ID, controlToAdd.AppRelativeVirtualPath); 
     } 
    } 
} 

TimeTeller.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="TimeTeller.ascx.cs" Inherits="DynamicControlTest.TimeTeller" %> 
<asp:Label ID="lblTime" runat="server"/> 

TimeTeller.ascx.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

namespace DynamicControlTest 
{ 
    public partial class TimeTeller : System.Web.UI.UserControl 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 

     } 

     public void SetTime(DateTime time) 
     { 
     lblTime.Text = time.ToString(); 
     } 

     protected override void LoadViewState(object savedState) 
     { 
     base.LoadViewState(savedState); 
     lblTime.Text = (string)ViewState["lblTime"]; 
     } 

     protected override object SaveViewState() 
     { 
     ViewState["lblTime"] = lblTime.Text; 
     return base.SaveViewState(); 
     } 
    } 
} 

जैसा कि आप देख सकते हैं, मुझे अभी भी अपने उपयोगकर्ता नियंत्रण के आंतरिक व्यूस्टेट को प्रबंधित करना है, लेकिन व्यूस्टेट बैग को पृष्ठ पर सहेजा जा रहा है और पोस्टबैक पर नियंत्रण में वापस सौंप दिया गया है। मुझे लगता है कि यह ध्यान रखना महत्वपूर्ण है कि मेरा समाधान डेविड के बहुत करीब है। मेरे उदाहरण में एकमात्र बड़ा अंतर यह है कि यह नियंत्रण जानकारी को स्टोर करने के लिए व्यूस्टेट के बजाय सत्र का उपयोग कर रहा है। यह शुरुआती चरण के दौरान चीजें होने की अनुमति देता है। यह ध्यान रखना महत्वपूर्ण है कि यह समाधान अधिक सर्वर संसाधन लेता है, इसलिए यह आपकी स्केलिंग रणनीति के आधार पर कुछ परिस्थितियों में उपयुक्त नहीं हो सकता है।

+0

मुझे वह विचार पसंद है, क्योंकि मैं वास्तव में उन सभी नियंत्रणों के आईडी (और शायद ऑर्डर) के साथ चिंतित हूं, जिन्हें मैं लोड करने की कोशिश कर रहा हूं। मैं उस समाधान के लिए एक त्वरित परीक्षण बिस्तर तैयार करूंगा और आपसे वापस आऊंगा। धन्यवाद! – mclark1129

+0

मुझे उम्मीद है कि आप इसे काम करने में सक्षम हैं। मुझे अतीत में कुछ ऐसा करना पड़ा। इनिट चरण में पृष्ठ पर नियंत्रण वापस लेना सबसे अच्छा है क्योंकि इस तरह नियंत्रण लाइफसाइकिल खेलने की उम्मीद है। मुझे यकीन है कि डेविड का समाधान काम करता है, लेकिन मुझे दीर्घकालिक रखरखाव के बारे में चिंतित होगा। मैंने इस तरह की चीजें भी की हैं और अंततः यह "ढांचे से लड़ने" परिदृश्य में बदल जाती है। आप आखिरकार ऐसी चीज में भाग ले सकते हैं जो जीवन के चक्र में देर से जोड़ते समय काम नहीं करेगा। –

+0

डैनियल, मैंने आपके सत्र समाधान का उपयोग करने में कुछ प्रगति की है लेकिन मैंने दो स्नैग मारा है। एक यह है कि इस तथ्य के बावजूद कि इनिट() चरण में नियंत्रण को पढ़ा जा रहा है, दृश्य राज्य को पुनर्स्थापित नहीं किया जा रहा है। मैं इस धारणा के तहत था कि जब इसे पढ़ा जा रहा है तो मुझे गतिशील नियंत्रण पर सेट करने की ज़रूरत है, दृश्य राज्य डेटा वापस पाने के लिए सही आईडी है, क्या मुझे कुछ याद आ रही है? साथ ही, सत्र डेटा तब भी जारी रहता है जब मैं पोस्ट-बैक का उपयोग नहीं कर रहा हूं। मैं बस सत्र को शून्य पर सेट कर दूंगा! पेज.इस्पोस्टबैक, लेकिन ध्वज इनिट() चरण के बाद तक सेट नहीं होता है। – mclark1129

3

मैंने पहले भी यह किया है। मुझे .NET 1.1 के दिनों से ऐसा नहीं करना पड़ा, लेकिन प्रिंसिपल इसे हटा देता है।

मैंने इसे पेज_लोड पर नहीं किया है, इनिट को पिछले पृष्ठ चक्र पर बनाए गए नियंत्रणों को फिर से लोड करना नहीं है।

सबसे पहले आपको प्रत्येक पृष्ठ चक्र पर बनाए गए नियंत्रणों का ट्रैक रखने की आवश्यकता है। इसमें प्रकार, नाम इत्यादि शामिल हैं। ।

फिर प्रत्येक पृष्ठ लोड पर आपको उन्हें पुनर्निर्माण करने की आवश्यकता है।

आप इसे फिर से बनाकर नियंत्रण बनाकर करते हैं, इसे सटीक वही आईडी मानते हैं, इसे पृष्ठ पर नमूना स्थान में जोड़ें और अंततः व्यूस्टेट ["लोडेड कंट्रोल"] में नियंत्रण प्रकार में जोड़ें।

यहां मैंने जो कोड इस्तेमाल किया है, मैंने केवल उपयोगकर्ता नियंत्रण के साथ ऐसा किया है। मैंने एएसपी.NET नियंत्रण के साथ यह कोशिश नहीं की है, लेकिन मुझे लगता है कि यह वही काम करेगा।

इस मामले में मेरे पास ट्रिपलेट्स का एक ऐरेलिस्ट है (ध्यान रखें कि यह .NET 1.1 है) adn पहली आइटम एक पृष्ठ दृश्य आईडी थी।आपको अपने आवेदन के लिए इसकी आवश्यकता नहीं हो सकती है।

protected void Page_Load(object sender, System.EventArgs e) 
{ 
    //********************************************************** 
    //* dynCtlArray will hold a triplet with the PageViewID, * 
    //* ControlID, and the Control Name      * 
    //********************************************************** 

    ArrayList dynCtlArray = (ArrayList)this.ViewState["dynCtlArray"]; 
    if (dynCtlArray != null) 
    { 

     foreach (object obj in dynCtlArray) 
     { 
      Triplet ctrlInfo = (Triplet)obj; 

      DynamicLoadControl(ctrlInfo); 
     } 
    } 
} 

private void DynamicLoadControl(Triplet ctrlInfo) 
{ 
    // ERROR HANDLING REMOVED FOR ANSWER BECAUSE IT IS NOT IMPORTANT YOU SHOULD HANDLE ERRORS IN THIS METHOD 

    Control ctrl = this.LoadControl(Request.ApplicationPath 
     + "/UC/" + (string)ctrlInfo.Third); 

    ctrl.ID = (string)ctrlInfo.Second; 

    // Create New PageView Item 
    Telerik.WebControls.PageView pvItem = this.RadMultiPage1.PageViews[(int)ctrlInfo.First]; 
    pvItem.Controls.Add(ctrl); 

    /****************************************************** 
    * The ControlName must be preserved to track the * 
    * currently loaded control       * 
    * ****************************************************/ 
    ViewState["LoadedControl"] = (string)ctrlInfo.Third; 
} 
private void RegisterDynControl(Triplet trip) 
{ 
    ArrayList dynCtlArray = (ArrayList)this.ViewState["dynCtlArray"]; 

    if (dynCtlArray == null) 
    { 
     dynCtlArray = new ArrayList(); 
     this.ViewState.Add("dynCtlArray", dynCtlArray); 
    } 

    dynCtlArray.Add(trip); 

} 
अपने पृष्ठ पर

कुछ विधि में

// Create new Control 
Control ctrl = Page.LoadControl("../UC/MyUserControl.ascx"); 

// . . . snip .. . 

// Create Triplet 
Triplet ctrlInfo = new Triplet(0, ctrl.ID, "MyUserControl.ascx"); 
// RegisterDynControl to ViewState 
RegisterDynControl(ctrlInfo); 

// . . . snip .. . 

वहाँ जानकारी को बचाने के लिए नियंत्रणों को ऐक्सेस करने के लिए आप क्या करना होगा एक this.Page.FindControl('');

+0

डेविड, प्रतिक्रिया के लिए बहुत बहुत धन्यवाद। मुझे अभी तक आपके समाधान का प्रयास करने का मौका नहीं मिला है, लेकिन इसे देखने में मुझे एक प्रश्न था: मैंने गतिशील नियंत्रण लोड करने के लिए अतीत में पेज_लोड का उपयोग किया है, लेकिन आमतौर पर लोड ईवेंट आने के बाद मुझे समस्याएं मिलती हैं व्यू स्टेट लोड किया गया है (इसलिए नियंत्रण आईडी की सरणी पाने की आपकी क्षमता)। नतीजतन, किसी भी उपयोगकर्ता द्वारा दर्ज किए गए मान पोस्टबैक पर खो गए हैं क्योंकि इस तथ्य के कारण कि दृश्य राज्य को तब लोड नहीं किया गया था जब दृश्य राज्य लोड किया गया था। क्या आप पेज पर इन नियंत्रणों को जोड़ने के तरीके को मैन्युअल रूप से अपना व्यू स्टेट लोड करते हैं? – mclark1129

+0

पेज_लोड को दृश्य स्थिति तक पहुंच होना चाहिए। लेकिन हाँ यह राज्य को वहां लोड करेगा। उदाहरण के लिए कहें कि आप गतिशील रूप से एक टेक्स्ट बॉक्स लोड कर रहे हैं। मेरी प्रक्रिया में आप 'इन नियंत्रणों पर ध्यान दें' पृष्ठ को बता रहे हैं, इसलिए लोड होने के बाद आप टेक्स्टबॉक्स का मूल्य प्राप्त कर सकते हैं, या इसकी किसी भी दृश्य स्थिति की जानकारी प्राप्त कर सकते हैं।आपको उस पृष्ठ को बताना होगा जिसे वे मैन्युअल रूप से बनाए गए थे अन्यथा पृष्ठ कभी इसे नहीं जानता होगा। –

1

मैंने डैनियल के उदाहरण के समान ही एक पृष्ठ लागू किया, लेकिन तकनीकी बाधाओं के कारण सत्र का उपयोग नहीं कर सका। हालांकि, मैंने पाया कि पृष्ठ पर किसी फ़ील्ड का उपयोग करके, मैं वापस पोस्ट कर सकता हूं और पेज_इनिट ईवेंट के दौरान अपना मूल्य पुनर्प्राप्त कर सकता हूं।

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

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