2011-01-12 22 views
9

我在winform中有幾個文本框,其中一些文本框位於groupbox內。我試圖循環遍歷我的所有形式的文本框:遍歷表單中的所有文本框,包括組框中的那些文本框

For Each c As Control In Me.Controls 
    If c.GetType Is GetType(TextBox) Then 
     ' Do something 
    End If 
Next 

但它似乎跳過這些組框和僅環比窗體的文本框等裏面。所以我增加了一個For Each循環,對組框中的文本框:

For Each c As Control In GroupBox1.Controls 
    If c.GetType Is GetType(TextBox) Then 
     ' Do something 
    End If 
Next 

我想知道:有沒有辦法來循環遍歷所有形式的文本框 - 包括一組框內部 - 與單個For Each循環?或者更好/更優雅的方式來做到這一點?

在此先感謝。

+0

的可能的複製[如何獲得一個Windows的所有子控件形成了一個特定的類型(按鈕/文本框)的形式?(https://stackoverflow.com/questions/3419159/how-to-get - 全兒童控制對的一 - 窗口表單的形式對的一特定類型的按鈕) – PulseJet 2017-06-22 05:18:48

回答

17

您可以使用此功能,linq可能是一個更優雅的方式。

Dim allTxt As New List(Of Control) 
For Each txt As TextBox In FindControlRecursive(allTxt, Me, GetType(TextBox)) 
    '....' 
Next 

Public Shared Function FindControlRecursive(ByVal list As List(Of Control), ByVal parent As Control, ByVal ctrlType As System.Type) As List(Of Control) 
    If parent Is Nothing Then Return list 
    If parent.GetType Is ctrlType Then 
     list.Add(parent) 
    End If 
    For Each child As Control In parent.Controls 
     FindControlRecursive(list, child, ctrlType) 
    Next 
    Return list 
End Function 
1

你會想要做遞歸,例如(僞代碼,因爲我不知道VB):

Sub LoopControls (Control Container) 
    if (Container has Controls) 
     LoopControls(Container) 
    For Each c As Control In Container 
     if (Control is TextBox) 
      // do stuff 
End Sub 

你會通過你的形式(我)給分開始,它會遍歷其中的控件,尋找包含更多控件的控件。

還檢查了這個問題:VB.NET - Iterating through controls in a container object

0

您將需要使用遞歸。以下是使用擴展方法的C#解決方案,它超出了您的問題的範圍,但我只是從我們的框架中提取它。

static partial class ControlExtensions 
{ 
    public static void ApplyToMatchingChild(this Control parent, Action<Control> actionToApplyWhenFound, bool keepApplyingForever, params Func<Control, bool>[] matchingChildCriteria) 
    { 
     ControlEventHandler reapplyEventHandler = null; 
     if (keepApplyingForever) 
     { 
      reapplyEventHandler = (s, e) => 
      { 
       ApplyToMatchingChild(e.Control, actionToApplyWhenFound, keepApplyingForever, matchingChildCriteria); 
      }; 
     } 
     SearchForMatchingChildTypes(parent, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria); 
    } 

    private static void SearchForMatchingChildTypes(Control control, Action<Control> actionToApplyWhenFound, ControlEventHandler reapplyEventHandler, params Func<Control, bool>[] matchingChildCriteria) 
    { 
     if (matchingChildCriteria.Any(criteria => criteria(control))) 
     { 
      actionToApplyWhenFound(control); 
     } 

     if (reapplyEventHandler != null) 
     { 
      control.ControlAdded += reapplyEventHandler; 
     } 

     if (control.HasChildren) 
     { 
      foreach (var ctl in control.Controls.Cast<Control>()) 
      { 
       SearchForMatchingChildTypes(ctl, actionToApplyWhenFound, reapplyEventHandler, matchingChildCriteria); 
      } 
     } 
    } 
} 

,並呼籲:

myControl.ApplyToMatchingChild(c => { /* Do Stuff to c */ return; }, false, c => c is TextBox); 

這將函數應用到所有子文本框。您可以使用keepApplyingForever參數來確保您的功能將在稍後添加子控件時應用。該功能還允許您指定任意數量的匹配標準,例如,如果控件也是標籤或其他標準。

實際上,我們使用這個方法來調用我們的依賴注入容器,以便將每個UserControl添加到我們的Form中。

我相信你也不應該有太多問題converting it to VB.NET ...另外,如果你不想要「keepApplyingForever」功能,它應該很容易去除。

0

如果你不關心控件的順序(我無法想象爲什麼你應該這麼做),你可以用下面的方式迭代地做到這一點(它非常簡單,所以我不認爲任何解釋都是必要的)。應該比任何遞歸更有效率,特別是如果你有很多嵌套控件,儘管我懷疑性能增益是否會顯而易見。

Public Function FindAllControlsIterative(ByRef parent As Control) As List(Of TextBox) 
    Dim list As New List(Of TextBox) 
    Dim ContainerStack As New Stack(Of Control) 
    ContainerStack.Push(parent) 
    While ContainerStack.Count > 0 
     For Each child As Control In ContainerStack.Pop().Controls 
      If child.HasChildren Then ContainerStack.Push(child) 
      If child.GetType Is GetType(TextBox) Then list.Add(child) 
     Next 
    End While 
    Return list 
End Function 
相關問題