2014-10-08 6 views
1

Так что моя программа генерирует кучу кнопок, как так:Как найти программно созданную кнопку по тексту?

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

+0

Мне действительно нужно было бы создать список кнопок, чтобы получить их? – Amorphous

+0

Эти кнопки отображаются на вашей форме? Вы уверены, что не хотите добавлять их в коллекцию управления вашей формой? Затем вы можете перебрать все кнопки в коллекции управления формы, чтобы найти интересующую вас кнопку, и есть даже удобные методы для этого. – CodeCaster

ответ

4

Вы можете использовать OfType<Button>, чтобы найти все кнопки в элементе управления контейнером, где вы их добавили (f .e. Panel). Тогда liitle мощность немного LINQ дает вам правильную кнопку (ы):

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(); 
1

Что-то вроде этого

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

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

2

Либо создать подкласс кнопки, чтобы сохранить информацию, которую вы хотите, и экземпляр, что вместо или использовать 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 араметр события нажатия кнопки в виде кнопки и проверки текста?

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

Как отметил Тим Шмельтер с моим ответом, это предполагает «равно», а не «содержит», как предлагает OP. Для этого также требуется знание состояния кода в кодовом режиме, поэтому вы просто должны указать обработчик события Click для другого обработчика для разных случаев (или добавить обработчик для дефолта), что, вероятно, противоречит духу вопроса. – AWinkle

0

Для того, чтобы получить ссылки, вам может понадобиться, что вы могли бы сделать с получением ссылок любого другого типа - хранить их где-то, что не кажется, что дело здесь вовсе. Обычно вы регистрируете свои кнопки для взаимодействия с пользователем, присоединяя их к Form. Предполагая, что вы не делаете этого по внешнему виду вашего образца кода, я собираюсь рекомендовать хранить их в Dictionary<string, Button>.

0

Вы можете использовать словарь, или вы можете использовать простой рекурсивный цикл (в случае, если торчат кнопки в различные контейнеры).

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);

Смежные вопросы