如何通过文本查找以编程方式创建的按钮?

问题描述:

所以我的程序产生一系列按钮,像这样:如何通过文本查找以编程方式创建的按钮?

foreach (var subdir in dir.GetDirectories()) { 
    var path = subdir.Name; 

    var button = new Button { 
     Text = getFlavor(path) + "\t(" + path + ")", 
     Width = Width, 
     Height = 35, 
     Top = y 
    }; 

    button.Click += buttonClick; 
    Controls.Add(button); 

    if (button.Text.Contains("Kittens") 
     i++; 
} 

我想尝试这样

if (i == 1) { 
     [Button.ThatContains("Kitten)].Click; 
} 

“ThatContains”的东西是不是一个真正的方法。我如何获得我已经以编程方式创建的按钮的引用?

+1

存储它的变量(或集合或字典)​​中,就像任何其他的价值。 – SLaks 2014-10-08 21:12:54

+0

我真的不得不创建一个按钮列表只是为了得到一个? – Amorphous 2014-10-08 21:13:46

+0

这些按钮是否显示在您的表单上?你确定你不想将它们添加到你的表单的控制集合吗?然后,您可以遍历表单控件集合中的所有按钮来查找您感兴趣的按钮,甚至还有方便的方法来完成此操作。 – CodeCaster 2014-10-08 21:14:08

您可以使用OfType<Button>查找已添加它们的容器控件中的所有按钮(f.e。a Panel)。然后,liitle位LINQ功率为您提供了正确的按钮(S):

var kittenButtons = panel.Controls.OfType<Button>() 
    .Where(btn => btn.Text.Contains("Kittens")); 
foreach(Button btn in kittenButtons) 
    btn.PerformClick(); 

如果你只是想点击第一:

Button kittenButton = panel.Controls.OfType<Button>() 
    .FirstOrDefault(btn => btn.Text.Contains("Kittens")); 
if(kittenButton != null) 
    kittenButton.PerformClick(); 

对于它的价值,这里也是一个扩展方法通过延迟执行递归执行,该方法允许仅使用第一个找到的Buttton或消耗所有的道路:

public static IEnumerable<T> GetChildControlsRecursive<T>(this Control root) where T : Control 
{ 
    if (root == null) throw new ArgumentNullException("root"); 
    var stack = new Stack<Control>(); 
    stack.Push(root); 
    while (stack.Count > 0) 
    { 
     Control parent = stack.Pop(); 
     foreach (Control child in parent.Controls) 
     { 
      if (child is T) 
       yield return (T)child; 
      stack.Push(child); 
     } 
    } 
    yield break; 
} 

现在你可以使用类似的代码按上述方法得到,例如第一个匹配的按钮或全部:

var kittenButtons = this.GetChildControlsRecursive<Button>() 
    .Where(b => b.Text.Contains("Kittens")); 
// search just until the first button is found 
Button firstKittenButton = kittenButtons.FirstOrDefault(); 
if(firstKittenButton != null) firstKittenButton.PerformClick; 
// loop all 
foreach(Button btn in kittenButtons) 
    btn.PerformClick(); 

像这样的事情

var button = FirstOrDefault(y => y is Button && y.Text.Contains("Kittens"));

if(button != null) button.PerformClick();

无论是创建按钮的子类来存储你想要的信息和实例化,而不是或使用Tag property

public class MyButton : Button 
{ 
    public int ButtonID { get; set; } 
} 

public class MyApplication 
{ 
    public void DoSomething() 
    { 
     int i; // todo: loop stuff 
     var button = new MyButton 
     { 
      Text = getFlavor(path) + "\t(" + path + ")", 
      Width = Width, 
      Height = 35, 
      Top = y, 
      ButtonID = i 
     }; 

    } 
} 

或者为什么不投送发件人p按钮点击事件的参数作为Button并检查文本?

public class MyApplication 
{ 
    public void DoSomething() 
    { 
     var b = new Button(); 
     b.Click += b_Click; 
    } 

    public void b_Click(object sender, EventArgs e) 
    { 
     Button b = (Button)sender; 
     switch (b.Text) { 
      case "Kittens": 
       return; 
      default: 
       return; 
     } 
    } 
} 
+0

正如Tim Schmelter用我的答案指出的,这个假定为“等于”而不是“包含”,如OP所示。这也需要代码时知道条件,所以你只需要让Click事件处理程序针对不同的情况指向不同的处理程序(或者在默认情况下不添加处理程序),这可能违背问题的精神。 – AWinkle 2014-10-08 21:53:48

为了得到引用,您可能需要您将与任何其他类型的获取引用做什么 - 它们存储的地方,这似乎并没有在这里是在所有的情况。通常情况下,您可以通过将用户的按钮附加到Form来注册按钮进行交互。假设你没有通过示例代码的外观来做这件事,我会建议将它们存储到Dictionary<string, Button>

你可以使用字典或者你可以使用一个简单的递归循环(如果你坚持的按钮进入不同的容器)。

private bool ClickButton(string buttonName, Control control) { 
     if (control is Button && control.Text.Contains(buttonName) { 
      ((Button)control)PerformClick(); 
      return true; 
     } 

     if (control.HasChildren) { 
      foreach (Control childControl in control.Controls) { 
       if (ClickButton(buttonName, childControl)) { 
        return true; 
       } 

      } 
     } 
     return false; 
    } 

用法:ClickButton("Kittens", this);

或者你可以使用一本字典,因为一些建议。

private Dictionary<string, Button> DynamicButtons = new Dictionary<string, Button>(); 

private void ClickDictionaryButton(string buttonName) { 
     var matches = DynamicButtons.Where(x => x.Key.Contains(buttonName)); 
     foreach (var match in matches) { 
      match.Value.PerformClick(); 
     } 
} 

用法:ClickDictionaryButton("Kittens", this);