LINQ

2008-10-31 9 views
33

साथ रिकर्सिव नियंत्रण खोज अगर मैं मैं निम्नलिखित LINQ क्वेरी इस्तेमाल कर सकते हैं एक ASP.NET पृष्ठ पर जाँच चेक बॉक्स को खोजने के लिए करना चाहता था।LINQ

var checkBoxes = this.Controls 
        .OfType<CheckBox>() 
        .TakeWhile<CheckBox>(cb => cb.Checked); 

कि ठीक काम करता है चेक बॉक्स वर्तमान नियंत्रण संग्रह में नेस्ट कर रहे हैं, लेकिन मुझे पता है कि शीर्ष स्तर के नियंत्रण के नियंत्रण संग्रह में गहरे उतर कर खोज का विस्तार करने के लिए कैसे करना चाहते हैं।

सवाल यहाँ कहा गया था:

Finding controls that use a certain interface in ASP.NET

और गैर LINQ उत्तर प्राप्त हुए, मैं पहले से ही प्रकार और आईडी विस्तार तरीके के रूप में पर एक पुनरावर्ती नियंत्रण खोज के अपने स्वयं के संस्करण है, लेकिन मैं अभी कैसे सोच LINQ में ऐसा करना आसान है?

उत्तर

43

प्रकार/आईडी प्रत्यावर्तन के बाहर की जाँच "रिकर्सिवली मुझे सभी नियंत्रण देते हैं," विधि ले लो, तो बस एक है, जैसे

public static IEnumerable<Control> GetAllControls(this Control parent) 
{ 
    foreach (Control control in parent.Controls) 
    { 
     yield return control; 
     foreach(Control descendant in control.GetAllControls()) 
     { 
      yield return descendant; 
     } 
    } 
} 

कि कुछ हद तक अक्षम (iterators की बहुत सारी बनाने के संदर्भ में) है, लेकिन मुझे शक है कि आप एक बहुत गहरी पेड़ होगा।

तब आप अपने मूल प्रश्न लिख सकते हैं:

var checkBoxes = this.GetAllControls() 
        .OfType<CheckBox>() 
        .TakeWhile<CheckBox>(cb => cb.Checked); 

(संपादित करें:। GetAllControls में बदला गया AllControls और एक विधि के रूप में ठीक से इसका इस्तेमाल करते हैं)

+0

काम करता है यही कारण है, लेकिन अगर आप तीसरे पक्ष के नियंत्रण और अपने खुद के सर्वर नियंत्रण हम अपने वर्तमान कार्यस्थल में कर के रूप में उपयोग कर रहे थे , आप नियंत्रण घोंसले के कुछ अच्छे स्तर प्राप्त कर सकते हैं। मुझे लगता है कि एक एएसपी.नेट पेज एक और सामान्य समस्या का एक उदाहरण है, जो कि लिंक में नेस्टेड संग्रहों के माध्यम से ड्रिलिंग का है। – PhilGriffin

+0

मैंने पहले इस तकनीक का उपयोग किया है। (यदि आप वास्तव में मीठा होना चाहते हैं, तो आप इसे वाई कॉम्बिनेटर के साथ एक अभिव्यक्ति के रूप में कर सकते हैं!) बीटीडब्ल्यू को ऑलकंट्रोल को विधि के रूप में उपयोग नहीं किया जाना चाहिए? – yfeldblum

+1

@ फिल: हाँ, यह कुछ स्तरों पर जा सकता है और थोड़ा अक्षम हो सकता है - लेकिन क्या आपके पास यह मानने का कोई कारण है कि यह एक * महत्वपूर्ण * बाधा होगी? सबसे आसान काम करें जो पहले काम करता है, और उसके बाद अनुकूलित करें यदि यह वास्तव में एक समस्या है। (उदाहरण के लिए एक ही डेटाबेस कॉल इस लागत को खत्म करने की संभावना है।) –

0

मेरे सुझाव AllControls पुनरावर्ती बनाना है:

public static IEnumerable<Control> AllControls(this Control parent) 
    { 
     foreach (Control control in parent.Controls) 
     { 
      yield return control; 
     } 
     foreach (Control control in parent.Controls) 
     { 
      foreach (Control cc in AllControls(control)) yield return cc; 
     } 
    } 

दूसरा foreach अजीब लग रहा है, लेकिन यह एक ही तरीका है मैं जानता हूँ कि पुनरावर्ती कॉल "समतल" के लिए है।

2
public static IEnumerable<Control> AllControls(this Control container) 
{ 
    //Get all controls 
    var controls = container.Controls.Cast<Control>(); 

    //Get all children 
    var children = controls.Select(c => c.AllControls()); 

    //combine controls and children 
    var firstGen = controls.Concat(children.SelectMany(b => b)); 

    return firstGen; 
} 

अब ऊपर कार्य के आधार पर, हम कुछ इस तरह कर सकते हैं:

public static Control FindControl(this Control container, string Id) 
{ 
    var child = container.AllControls().FirstOrDefault(c => c.ID == Id); 
    return child; 
} 

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

  • कोई संबंधित समस्या नहीं^_^