2013-09-30 3 views
0

Привет, мне было интересно, как я могу следить за всем textboxes в форме, было ли в любом из них изменено значение. Я видел некоторый код hereНазначение события TextChanged для всех текстовых полей в форме

private void Form1_Load(object sender, EventArgs e) 
{ 
    foreach (Control ctrl in this.Controls) 
    { 
     if (ctrl is TextBox) 
     { 
      TextBox tb = (TextBox)ctrl; 
      tb.TextChanged += new EventHandler(tb_TextChanged); 
     } 
    } 
} 

void tb_TextChanged(object sender, EventArgs e) 
{ 
    TextBox tb = (TextBox)sender; 
    tb.Tag = "CHANGED"; // or whatever 
} 

И парень, который написал этот код говорит, что «не может быть назначен в текстовые поля панели и Grouboxes».

Итак, мой вопрос заключается в том, что у меня почти все текстовые поля в groubox или панели, как я могу узнать, было ли внесено изменение для текстовых полей в панелях или групповом поле?

+0

Вы уже пробовали? – meilke

+3

Я думаю, что единственная причина, по которой это не сработает, - это то, что вы не итерируете детей 'this.Controls'. То есть Form -> Panel -> TextBox, поэтому вам нужно сделать свой цикл рекурсивным и проверить всех детей детей и т. Д., Чтобы проверить все текстовые поля в форме. – Belogix

ответ

4

Вы можете сделать свой метод рекурсивного:

private void Form1_Load(object sender, EventArgs e) 
{ 
    Assign(this); 
} 

void Assign(Control control) 
{ 
    foreach (Control ctrl in control.Controls) 
    { 
     if (ctrl is TextBox) 
     { 
      TextBox tb = (TextBox)ctrl; 
      tb.TextChanged += new EventHandler(tb_TextChanged); 
     } 
     else 
     { 
      Assign(ctrl); 
     } 
    } 
} 

void tb_TextChanged(object sender, EventArgs e) 
{ 
    TextBox tb = (TextBox)sender; 
    tb.Tag = "CHANGED"; // or whatever 
} 

Просто найти лучшее название для метода вместо Assign.

3

Когда вам нужно иметь дело с вложенными элементами управления, 1 для цикла не может помочь. Вы должны использовать некоторые рекурсивный метод или пользовательские stack для перебора всех элементов управления, что-то вроде этого:

private void RegisterTextChangedEventHandler(Control root){ 
    Stack<Control> stack = new Stack<Control>(); 
    stack.Push(root); 
    Control current = null;  
    while(stack.Count>0){ 
     current = stack.Pop(); 
     foreach(var c in current.Controls){ 
     if(c is TextBox) ((TextBox)c).TextChanged += textChanged; 
     stack.Push(c); 
     } 
    } 
} 
private void textChanged(object sender, EventArgs e){ 
    //.... 
} 
//Use it 
RegisterTextChangedEventHandler(yourForm);//Or your container .... 
+1

Думайте, что это может потребоваться небольшая настройка, потому что вы только нажимаете детей на стек, если ребенок является TextBox, тогда как вы хотите только нажать, если это ** NOT ** TextBox? Кроме этого, очень чистый код/​​реализован! – Belogix

+0

@Belogix Спасибо, небольшая ошибка. На самом деле, я также хочу разрешить push TextBox в стек, иначе использовать 'else' в порядке, просто обновил код. –

1

Вам нужен другой цикл для groupbox и panels, вы можете использовать этот код:

private void addEvents(Control.ControlCollection ct) 
{ 
    foreach (Control ctrl in ct) 
    { 
     if (ctrl is TextBox) 
     { 
      TextBox tb = (TextBox)ctrl; 
      tb.TextChanged += new EventHandler(tb_TextChanged); 
     } 
     else if (ctrl is GroupBox || ctrl is Panel) addEvents(ctrl.Controls); 
    } 
} 

private void Form1_Load(object sender, EventArgs e) 
{ 
    addEvents(this.Controls); 
} 

void tb_TextChanged(object sender, EventArgs e) 
{ 
    TextBox tb = (TextBox)sender; 
    tb.Tag = "CHANGED"; // or whatever 
} 
Смежные вопросы