2011-09-09 17 views
27

Tôi đã được cân nhắc làm thế nào tôi có thể nhận được tất cả các điều khiển trên một trang và sau đó thực hiện một nhiệm vụ trên chúng trong câu hỏi có liên quan này:Get All Controls Web của một loại hình cụ thể trên một trang

How to Search Through a C# DropDownList Programmatically

tôi cần mã có thể quét trang, nhận tất cả các điều khiển DropDownList và trả lại chúng trong một danh sách.

Tôi hiện đang phải chỉnh sửa từng điều khiển riêng lẻ, tôi muốn có thể tự động lặp qua từng điều khiển để tạo thành công việc của mình.

Trả lời

50

Kiểm tra my previous SO answer.

Về cơ bản, ý tưởng là để bọc các đệ quy của iterating thông qua các bộ sưu tập điều khiển sử dụng:

private void GetControlList<T>(ControlCollection controlCollection, List<T> resultCollection) 
where T : Control 
{ 
    foreach (Control control in controlCollection) 
    { 
     //if (control.GetType() == typeof(T)) 
     if (control is T) // This is cleaner 
      resultCollection.Add((T)control); 

     if (control.HasControls()) 
      GetControlList(control.Controls, resultCollection); 
    } 
} 

và sử dụng nó:

List<DropDownList> allControls = new List<DropDownList>(); 
GetControlList<DropDownList>(Page.Controls, allControls) 
foreach (var childControl in allControls) 
{ 
//  call for all controls of the page 
} 

[Sửa 2013/11/26] : đây là một cách thanh lịch hơn để đạt được mục tiêu này. Tôi đã viết hai phương pháp mở rộng có thể đi bộ cây điều khiển theo cả hai hướng. Các phương pháp được viết bằng một LINQ cách hơn vì nó tạo ra một đếm được:

/// <summary> 
/// Provide utilities methods related to <see cref="Control"/> objects 
/// </summary> 
public static class ControlUtilities 
{ 
    /// <summary> 
    /// Find the first ancestor of the selected control in the control tree 
    /// </summary> 
    /// <typeparam name="TControl">Type of the ancestor to look for</typeparam> 
    /// <param name="control">The control to look for its ancestors</param> 
    /// <returns>The first ancestor of the specified type, or null if no ancestor is found.</returns> 
    public static TControl FindAncestor<TControl>(this Control control) where TControl : Control 
    { 
     if (control == null) throw new ArgumentNullException("control"); 

     Control parent = control; 
     do 
     { 
      parent = parent.Parent; 
      var candidate = parent as TControl; 
      if (candidate != null) 
      { 
       return candidate; 
      } 
     } while (parent != null); 
     return null; 
    } 

    /// <summary> 
    /// Finds all descendants of a certain type of the specified control. 
    /// </summary> 
    /// <typeparam name="TControl">The type of descendant controls to look for.</typeparam> 
    /// <param name="parent">The parent control where to look into.</param> 
    /// <returns>All corresponding descendants</returns> 
    public static IEnumerable<TControl> FindDescendants<TControl>(this Control parent) where TControl : Control 
    { 
     if (parent == null) throw new ArgumentNullException("control"); 

     if (parent.HasControls()) 
     { 
      foreach (Control childControl in parent.Controls) 
      { 
       var candidate = childControl as TControl; 
       if (candidate != null) yield return candidate; 

       foreach (var nextLevel in FindDescendants<TControl>(childControl)) 
       { 
        yield return nextLevel; 
       } 
      } 
     } 
    } 
} 

Nhờ có từ khóa this, những phương pháp này mở rộng phương pháp và có thể đơn giản hóa mã.

Ví dụ, để tìm tất cả DropDownList trong trang, bạn chỉ có thể gọi:

var allDropDowns = this.Page.FindControl<DropDownList>(); 

Bởi vì việc sử dụng các từ khóa yield, và vì LINQ là đủ thông minh để trì hoãn việc thực hiện các kiểu liệt kê, bạn có thể gọi (ví dụ):

var allDropDowns = this.Page.FindDescendants<DropDownList>(); 
var firstDropDownWithCustomClass = allDropDowns.First(
    ddl=>ddl.CssClass == "customclass" 
    ); 

Việc liệt kê sẽ dừng lại ngay khi có biến vị ngữ trong phương pháp First. Toàn bộ cây điều khiển sẽ không được đi.

+1

Câu trả lời toàn diện nhất và nó hoạt động như một sự cổ vũ. – Anicho

+0

http://msdn.microsoft.com/en-us/library/yt340bh4.aspx Bài viết hay về msdn là tốt. – Anicho

+0

Tôi thích nó. Thật tốt là tôi không còn cần phải sử dụng một từ khóa lợi nhuận, mà làm cho nó để chức năng đệ quy luôn luôn chạy mặc dù tôi tuyên bố Visual Studio để bước qua nó. – JonathanWolfson

0
 var dropDownLists = new List<DropDownList>(); 
     foreach (var control in this.Controls) 
     { 
      if (control is DropDownList) 
      { 
       dropDownLists.Add((DropDownList)control); 
      } 
     } 
+7

Tôi khá chắc chắn bạn cần phải tái chế. – SLaks

2

Điều khiển vòng lặp trên trang không khó - bạn chỉ cần xem xét bên trong mỗi điều khiển để có nhiều điều khiển hơn.

Bạn có thể làm một cái gì đó giống như

foreach(var control in Page) 
{ 
    if(control is DropDownList) 
    { 
     //Do whatever 
    } 
    else 
    { 
     //Call this function again to search for controls within this control 
    } 
} 
+2

Điều này sẽ không hoạt động. Cần phải đệ quy. –

+2

Đó là những gì người khác dành cho ... // Gọi chức năng này một lần nữa để tìm kiếm các điều khiển trong điều khiển này ... đang kêu gọi một cái gì đó recurisve ... –

1

Bạn có thể sử dụng logic đệ quy để có được tất cả các điều khiển, như thế này:

private void PopulateSelectList(Control parentCtrl, List<DropDownList> selectList) 
{ 
    foreach (Control ctrl in parentCtrl.Controls) 
    { 
     if (ctrl is DropDownList) 
     { 
      selectList.Add(((DropDownList)ctrl); 
      continue; 
     } 
     FindAllControls(ctrl, selectList); 
    } 
} 
14
foreach (DropDownList dr in this.Page.Form.Controls.OfType<DropDownList>()) 
{ 

} 
+0

một trong số ít nhất liều lượng mã giống nhau xD – Anicho

+2

Để làm việc này đúng, nó nên đệ quy. –

+0

Vâng! Bạn cần phải lặp lại từng điều khiển Bộ sưu tập điều khiển - đệ quy. Nhưng những phương pháp mở rộng này tôi nghĩ là thực sự hữu ích, bởi vì chúng làm cho mã của bạn nhỏ gọn hơn - làm việc nhiều hơn trong ít dòng hơn. – marko

5

Đã câu hỏi này rất và trong khi tôi tìm thấy câu trả lời Steve B hữu ích, tôi muốn một phương pháp mở rộng, vì vậy tái yếu tố nó:

public static IEnumerable<T> GetControlList<T>(this ControlCollection controlCollection) where T : Control 
    { 
     foreach (Control control in controlCollection) 
     { 
      if (control is T) 
      { 
       yield return (T)control; 
      } 

      if (control.HasControls()) 
      { 
       foreach (T childControl in control.Controls.GetControlList<T>()) 
       { 
        yield return childControl; 
       } 
      } 
     } 
    } 
+0

Tôi gặp lỗi intelli-sense về "this" nói "Type expected". Tôi chỉ đơn giản là thêm này vào một lớp học trong thư mục app_code. – Fandango68

4

Đây là một phiên bản đệ quy mà trả về một bộ sưu tập kiểm soát loại được yêu cầu thay vì sử dụng một đối số khác:

using System.Collections.Generic; 
using System.Web.UI; 
// ... 
public static List<T> GetControls<T>(ControlCollection Controls) 
where T : Control { 
    List<T> results = new List<T>(); 
    foreach (Control c in Controls) { 
    if (c is T) results.Add((T)c); 
    if (c.HasControls()) results.AddRange(GetControls<T>(c.Controls)); 
    } 
    return results; 
} 

Chèn vào lớp của bạn (tùy chọn tĩnh).

0

Điều này có tác dụng nếu bạn sử dụng các thành phần biểu mẫu từ system.web.ui tuy nhiên điều này không hoạt động khi bạn sử dụng chúng từ system.web.mvc rõ ràng vì vậy tôi đã tìm ra công việc sau đây.

for (Int32 idx = 0; idx < formCollection.Count; idx += 1) 
        { 
        String Name = formCollection.Keys[idx]; 
        String value = formCollection[idx]; 

        if (Name.Substring(0, 3).ToLower() == "chk") 

         { 
         Response.Write(Name + " is a checkbox <br/>"); 
         } 
        else if (Name.Substring(0, 5).ToLower() == "txtar") 
         { 
         Response.Write(Name + " is a text area <br/>"); 
         } 
        else if (Name.Substring(0, 2).ToLower() == "rd") 
         { 
         Response.Write(Name + " is a RadioButton <br/>"); 
         } 

        } 

này làm việc cho tôi nhưng tôi phát hiện ra rằng nút radio nếu không được chọn là null nên doesnt trở lại bất cứ điều gì đó là ok tôi không phải viết bất cứ điều gì để các cơ sở dữ liệu nếu nó là null

Các vấn đề liên quan