我一直在琢磨怎樣才能得到一個網頁上的所有控件,然後在此相關的問題對他們執行任務:得到一個特定類型的所有Web控件在頁面上
How to Search Through a C# DropDownList Programmatically
我需要可以掃描頁面的代碼,獲取所有DropDownList控件並將它們返回到列表中。
我目前不得不編輯每個單獨的控件,我寧願能夠動態循環每個控件來完成我的任務。
我一直在琢磨怎樣才能得到一個網頁上的所有控件,然後在此相關的問題對他們執行任務:得到一個特定類型的所有Web控件在頁面上
How to Search Through a C# DropDownList Programmatically
我需要可以掃描頁面的代碼,獲取所有DropDownList控件並將它們返回到列表中。
我目前不得不編輯每個單獨的控件,我寧願能夠動態循環每個控件來完成我的任務。
基本上,這個想法是包裹使用通過控制集合迭代的遞推:
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);
}
}
和使用它:
List<DropDownList> allControls = new List<DropDownList>();
GetControlList<DropDownList>(Page.Controls, allControls)
foreach (var childControl in allControls)
{
// call for all controls of the page
}
[編輯2013年11月26日] :這是達到這個目標的更優雅的方式。我寫了兩個可以在兩個方向上走控制樹的擴展方法。這些方法都寫在一個更LINQ的方式,因爲它產生一個可枚舉:
/// <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;
}
}
}
}
}
得益於this
關鍵字,這些方法擴展的方法和可以簡化代碼。
例如,要查找頁面中所有DropDownList
,您只需撥打:
var allDropDowns = this.Page.FindControl<DropDownList>();
因爲使用了yield
關鍵字的,因爲LINQ的是足夠聰明推遲枚舉的執行,你可以撥打電話(例如):
var allDropDowns = this.Page.FindDescendants<DropDownList>();
var firstDropDownWithCustomClass = allDropDowns.First(
ddl=>ddl.CssClass == "customclass"
);
枚舉將盡快在First
方法謂語滿足停止。整個控制樹不會走。
var dropDownLists = new List<DropDownList>();
foreach (var control in this.Controls)
{
if (control is DropDownList)
{
dropDownLists.Add((DropDownList)control);
}
}
我敢確定你需要緩解。 – SLaks
通過頁面上的控件循環不難 - 你只需要在每個控件中查看更多的控件。
你可以做類似
foreach(var control in Page)
{
if(control is DropDownList)
{
//Do whatever
}
else
{
//Call this function again to search for controls within this control
}
}
這不起作用。需要遞歸。 –
這就是其他的是... //再次調用這個函數來搜索這個控件中的控件......這就是要求恢復的東西... –
您可以使用遞歸的邏輯來獲得所有的控制,就像這樣:
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);
}
}
曾有過這個問題,雖然我發現史蒂夫B的回答有用,我想一個擴展方法,所以重新分解它:
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;
}
}
}
}
我在「this」上顯示「Type expected」時出現智能錯誤。我只是將其添加到app_code文件夾中的類中。 – Fandango68
這裏是一個遞歸版本,返回的控制集合請求的類型而不是利用另一個參數:
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;
}
插入到您的類(靜態可選)。
如果您使用system.web.ui 中的表單組件,那麼這個方法可行,但是當您從system.web.mvc中顯式使用它們時,這不起作用,所以我想出了以下解決方法。
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/>");
}
}
這對我的作品,但是我發現,如果沒有選中的單選按鈕是空,因此犯規返回任何這是確定我沒有寫任何東西到數據庫中,如果它是空
最全面的答案,它的作品就像一個魅力的歡呼夥計。 – Anicho
http://msdn.microsoft.com/en-us/library/yt340bh4.aspx關於msdn的好文章很好。 – Anicho
我喜歡它。很好,我不再需要使用yield關鍵字,這使得遞歸函數始終運行,即使我聲明Visual Studio跨越它。 – JonathanWolfson