如何通过文本查找以编程方式创建的按钮?
所以我的程序产生一系列按钮,像这样:如何通过文本查找以编程方式创建的按钮?
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”的东西是不是一个真正的方法。我如何获得我已经以编程方式创建的按钮的引用?
您可以使用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;
}
}
}
正如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);
存储它的变量(或集合或字典)中,就像任何其他的价值。 – SLaks 2014-10-08 21:12:54
我真的不得不创建一个按钮列表只是为了得到一个? – Amorphous 2014-10-08 21:13:46
这些按钮是否显示在您的表单上?你确定你不想将它们添加到你的表单的控制集合吗?然后,您可以遍历表单控件集合中的所有按钮来查找您感兴趣的按钮,甚至还有方便的方法来完成此操作。 – CodeCaster 2014-10-08 21:14:08