Reputation: 697
So my program is generating a bunch of buttons like so:
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++;
}
I want to try something like this
if (i == 1) {
[Button.ThatContains("Kitten)].Click;
}
"ThatContains" is not a real method. How do I get references to buttons I've created programmatically ?
Upvotes: 1
Views: 287
Reputation: 460058
You could use OfType<Button>
to find all buttons in the container control where you've added them(f.e. a Panel
). Then a liitle bit LINQ power gives you the correct button(s):
var kittenButtons = panel.Controls.OfType<Button>()
.Where(btn => btn.Text.Contains("Kittens"));
foreach(Button btn in kittenButtons)
btn.PerformClick();
If you just want to click the first:
Button kittenButton = panel.Controls.OfType<Button>()
.FirstOrDefault(btn => btn.Text.Contains("Kittens"));
if(kittenButton != null)
kittenButton.PerformClick();
For what it's worth, here is also an extension method that returns controls recursively via deferred execution which allows to use only the first found Buttton
or consume all down the road:
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;
}
Now you can use similar code as above to get for example the first matching button or all:
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();
Upvotes: 4
Reputation: 673
You could use a dictionary or you could use a simple recursive loop (in case you are sticking the buttons into different containers).
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;
}
Usage: ClickButton("Kittens", this);
Or you could use a dictionary, as some have suggested.
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();
}
}
Usage: ClickDictionaryButton("Kittens", this);
Upvotes: 0
Reputation: 1978
Either create a subclass of Button to store the information you want and instantiate that instead or use the 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
};
}
}
Or why not cast the sender parameter of the button click event as a Button and check the text?
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;
}
}
}
Upvotes: 2
Reputation: 8852
Something like this
var button = FirstOrDefault(y => y is Button && y.Text.Contains("Kittens"));
if(button != null)
button.PerformClick();
Upvotes: 1
Reputation: 10708
In order to get the references, you may need to what you would do with getting references of any other type - store them somewhere, which does not seem to be the case here at all. Normally, you would register your buttons for interaction from a user by attaching them to a Form
. Assuming you're not doing this by the looks of your sample code, I'm going to recommend storing them into a Dictionary<string, Button>
.
Upvotes: 0