2010-11-27 33 views
6

के भीतर नियंत्रणों का नियंत्रण मैं एक वेबसाइट तैयार कर रहा हूं जिसमें पृष्ठ पर ग्रिड है। ग्रिड में इसके अंदर कई कॉम्बोबॉक्स हैं। ये comboboxes बातचीत करते हैं। यानी जब उपयोगकर्ता द्वारा एक मान बदल दिया जाता है तो किसी के पास इसका मूल्य परिवर्तन होता है या अक्षम/सक्षम आदि होता हैग्रिड

मुझे ऐसा करने के लिए मिलते हैं मुझे FindControl का उपयोग करना होगा। एक combobox के चयनितindexchanged घटना की तरह मुझे एक और कॉम्बोबॉक्स खोजने की आवश्यकता होगी।

यह चीजों को करने का एक गन्दा तरीका लगता है। ऐसा लगता है कि यह सिस्टम को त्रुटियों के लिए खुला छोड़ देता है, संकलक नहीं कहेंगे कि अगर एक combobox के बाद यह लाइन नीचे लाइन पर बदल गया है।

क्या कोई मुझे बता सकता है कि इस बारे में जाने का एक बेहतर तरीका है?

उत्तर

0

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

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

मुझे पता है, सबसे अच्छा विचार नहीं, बल्कि मेरे सिर के ऊपर से। हो सकता है कि जब मेरे पास इस पर और सोचने का समय हो तो मैं इस पोस्ट को अपडेट कर सकता हूं।

1

मेरे पास एक वेब ऐप है जो आपके वर्णन के अनुसार विभिन्न FindControl क्रमपरिवर्तनों का व्यापक उपयोग करता है। हालांकि यह भंगुर है (परीक्षण के बिना नियंत्रण आईडी नहीं बदलें), इसे कुछ उपयोगिता कार्यों के माध्यम से थोड़ा कम बोझिल बनाया जा सकता है। यहां मेरे द्वारा उपयोग किए जाने वाले सभी FindControl-type फ़ंक्शंस हैं - यह कम से कम आपकी सहायता कर सकता है।

/// <summary> 
/// Recursively searches for a control within the heirarchy of a given control. 
/// </summary> 
/// <param name="root">The control to search within.</param> 
/// <param name="id">The ID of the control to find.</param> 
/// <returns>The Control object of the found control, or null if the control isn't found.</returns> 
public static Control FindControlRecursive(Control root, string id) 
{ 
    if (root.ID == id) return root; 

    foreach (Control c in root.Controls) 
    { 
     Control t = FindControlRecursive(c, id); 
     if (t != null) return t; 
    } 

    return null; 
} 

/// <summary> 
/// Recursively searches for a control within the heirarchy of a given control using the Client ID 
/// of the control. Calling this too early in the lifecycle may not behave as expected. 
/// </summary> 
/// <param name="root">The control to search within.</param> 
/// <param name="clientID">The Client ID of the control to find.</param> 
/// <returns>The Control object of the found control, or null if the control isn't found.</returns> 
public static Control FindControlRecursiveByClientID(Control root, string clientID) 
{ 
if (0 == String.Compare(root.ClientID, clientID, true)) return root; 

foreach (Control c in root.Controls) 
{ 
    Control t = FindControlRecursiveByClientID(c, clientID); 
    if (t != null) return t; 
} 

return null; 
} 

/// <summary> 
/// Recursively searches for a group of controls within the heirarchy of a given control tree using the ID 
/// of the control. 
/// </summary> 
/// <param name="root">The control tree to search within.</param> 
/// <param name="id">The ID of the control to find.</param> 
/// <returns> 
/// A collection of the found controls. The collection will be empty if none are found. 
/// </returns> 
public static List<Control> FindControlsRecursive(Control root, string id) 
{ 
List<Control> collection = new List<Control>(); 
FindControlRecursive(root, id, collection); 
return collection; 
} 

private static void FindControlRecursive(Control root, string id, List<Control> collection) 
{ 
foreach (Control c in root.Controls) 
{ 
    if (0 == String.Compare(c.ID, id, true)) collection.Add(c); 
    else FindControlRecursive(c, id, collection); 
} 
} 

/// <summary> 
/// Recursively searches for a control within the heirarchy of a given control using the type 
/// of the control. 
/// </summary> 
/// <typeparam name="T">The type of the control to find.</typeparam> 
/// <param name="root">The control to search within.</param> 
/// <returns> 
/// The Control object of the found control, or null if the control isn't found. 
/// </returns> 
public static T FindControlRecursiveByType<T>(Control root) 
where T : Control 
{ 
if (root is T) return (T)root; 
foreach (Control c in root.Controls) 
{ 
    Control t = FindControlRecursiveByType<T>(c); 
    if (t != null) return (T)t; 
} 
return null; 
} 

/// <summary> 
/// Recursively searches for a set of controls within the heirarchy of a given control using the type 
/// of the control. 
/// </summary> 
/// <typeparam name="T">The type of the control to find.</typeparam> 
/// <param name="root">The control to search within.</param> 
/// <returns> 
/// A generic List object containing the controls found, or an empty List of none were found. 
/// </returns> 
public static List<T> FindControlsRecursiveByType<T>(Control root) 
where T : Control 
{ 
List<T> collection = new List<T>(); 
FindControlRecursiveByType<T>(root, collection); 
return collection; 
} 

private static void FindControlRecursiveByType<T>(Control root, List<T> collection) 
where T : Control 
{ 
foreach (Control c in root.Controls) 
{ 
    if (c is T) collection.Add((T)c); 
    else FindControlRecursiveByType<T>(c, collection); 
} 
} 
0

अधिसूचनाओं को करने के लिए घटनाओं का उपयोग करने के बारे में कैसे?

0

ये बहुत गन्दा हैं।

यहां एक बहुत ही सरल और सुरुचिपूर्ण समाधान है। कहें कि आपकी ग्रिड को 3 कॉलम वाले टेबल में डेटा प्रदर्शित करने की आवश्यकता है। डेटा निम्नलिखित संरचना के साथ एक वस्तु से आ रही है:

मार्कअप (GridDisplayRow.ascx):

[Serializable] 
public class Foo 
{ 
    public string Bar1 { get; set; } 
    public string Bar2 { get; set; } 
    public string Bar3 { get; set; } 
} 

फिर अपने उपयोगकर्ता नियंत्रण निम्न मार्कअप होगा

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="GridDisplayRow.ascx.cs" Inherits="GridDisplayRow" %> 
<div> 
    <div class="cell"> 
     <asp:TextBox id="TxtProperty1" runat="server"/> 
    </div> 
    <div class="cell"> 
     <asp:DropDownList ID="DDLProperty2" runat="server" OnSelectedIndexChanged="DDLProperty2_OnSelectedIndexChanged" AutoPostBack="true"> 
     </asp:DropDownList> 
    </div> 
    <div class="cell"> 
     <input type="radio" id="RadProperty3" runat="server"> 
    </div> 
</div> 

सूचना सभी div टैग बच्चों के div तैर रहे हैं ... ताकि वे एक तरफ प्रदर्शित करते हैं।

codebehind (GridDisplayRow.ascx.cs):

class GridDisplayRow:UserControl 
{ 
    public event EventHandler<System.EventArgs> SomethingHappened; 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     //Initialize the drop down with something; 
    } 

    //this is where we handle internal events generated by children controls. 
    //Eg: the drop down's index changed. 
    protected void DDLProperty2_OnSelectedIndexChanged(object sender, EventArgs e) 
    { 
     //we update some other child control in this... 
     this.TxtProperty1.Text = this.DDLProperty2.Value; 

     //and maybe we want to signal the page that some event happened 
     if(SomethingHappened != null) 
     { 
      //Notify the page that SomethingHappened event occured 
      SomethingHappened(this, EventArgs.Empty); 
     } 
    } 

    //This is where the binding happens 
    public object BindingObject 
    { 
     set 
     { 
      Foo temp = (Foo)value; 
      this.TxtProperty1.Text = temp.Bar1; 
      this.DDLProperty2.Value = temp.Bar2; 
      this.RadProperty3.Value = temp.Bar3; 

      this.ViewState["Foo"] = temp; 
     } 
    } 
} 

तो कोड ऊपर हम संभाल रहे हैं में फू के लिए बाध्य, दूसरे शब्दों में हम प्रत्येक कोशिका में फू के गुण प्रदर्शित कर रहे हैं (div) नियंत्रण से ।कास्ट की आवश्यकता है क्योंकि ऊपर की संपत्ति प्रकार की वस्तु है, और ग्रिड/रिपेटर के आइटम टेम्पलेट में/आप क्या हैं, आप GridDisplayRow के कंटेनर। डेटाटाइम ऑब्जेक्ट के उदाहरण को बाध्य दिखाएंगे।

पृष्ठ मार्कअप::

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" %> 
<%@ Register src="GridDisplayRow.ascx" tagname="GridRow" tagprefix="ctrl" %> 

<asp:GridView ID="GridView1" runat="server"> 
    <Columns> 
     <asp:TemplateField> 
      <HeaderTemplate> 
       <div> 
        <div class="header cell">Header 1</div> 
        <div class="header cell">Header 2</div> 
        <div class="header cell">Header 3</div> 
       </div> 
      </HeaderTemplate> 
      <ItemTemplate> 
       <ctrl:GridRow ID="Row" runat="server" BindingObject='<%# Container.DataItem %>' OnSomethingHappened="Row_SomethingHappened" /> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

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

कृपया ध्यान दें कि यह एक पुनरावर्तक के साथ बेहतर काम करता है क्योंकि यह सुपर कुशल है और इसमें कम ओवरहेड है!

अब ग्रिड को बाध्यकारी: किसी भी स्रोत जो IENumerable लागू करता है, को ग्रिड से बांधने के लिए उपयोग किया जा सकता है। चूंकि सूची जैसे संग्रह पर्याप्त होंगे।

जब ग्रिडरो नियंत्रण अपनी घटनाओं को सक्रिय करता है, तो नियंत्रण का संदर्भ ऑब्जेक्ट प्रेषक के माध्यम से भेजा जाता है, इस प्रकार यदि आप प्रेषक को अपने सही प्रकार पर डालते हैं तो आप नियंत्रण के आंतरिक गुणों को पकड़ सकते हैं .... संभावनाएं अनंत हैं।

ऐसी विधि का लाभ अमूर्त है। प्रत्येक नियंत्रण अपनी घटनाओं को संभाल सकता है, या इसके अंदर होने वाली घटनाओं के पृष्ठ को सूचित करने के लिए चुना है .... bla bla bla। तुम्हें नया तरीका मिल गया है।

0

ListView का उपयोग करने का प्रयास करें, इस तरह की आवश्यकताओं को प्रबंधित करना अधिक आसान है। यदि आप ListView को Update Panel के अंदर डालते हैं तो आपके पास बेहतर उपयोगकर्ता अनुभव

हो सकता है