2009-02-11 18 views
13

Estoy creando un TextBox y una Button dinámicamente usando el siguiente código:WPF ¿cómo creo un cuadro de texto de forma dinámica y encuentro el cuadro de texto con un clic de botón?

Button btnClickMe = new Button(); 
btnClickMe.Content = "Click Me"; 
btnClickMe.Name = "btnClickMe"; 
btnClickMe.Click += new RoutedEventHandler(this.CallMeClick); 

someStackPanel.Childern.Add(btnClickMe); 

TextBox txtNumber = new TextBox(); 
txtNumber.Name = "txtNumber"; 
txtNumber.Text = "1776"; 

someStackPanel.Childern.Add(txtNumber); 

puedo conectar a un evento de clic al botón Click Me. El botón "clic en mí" incluso se dispara correctamente. Sin embargo, no puedo encontrar el TextBox que ingresé dinámicamente.

Aquí está mi me haga clic en evento:

protected void ClickMeClick(object sender, RoutedEventArgs e) 
{ 
    // Find the phone number 
    TextBox txtNumber = this.someStackPanel.FindName("txtNumber") as TextBox; 

    if (txtNumber != null) 
    { 
     string message = string.Format("The number is {0}", txtNumber.Text); 

     MessageBox.Show(message);  
    } 
    else 
    { 
     MessageBox.Show("Textbox is null"); 
    } 
} 

¿Cómo puedo encontrar el TextBoxtxtNumber?

+0

¿quisiste decir this.someStackPanel.FindName ("txtNumber")? – foson

+0

Gracias lo arreglé. Todavía no funciona. –

+0

Un montón de errores tipográficos en esta: (1) s/Childern/niños/ (2) Botón se encamina a CallMeClick pero el código muestra ClickMeClick (3) Botón se coloca en someStackPanel pero más tarde se busca en pnlCallMe Evidentemente, esta no es el código que está ejecutando. – hughdbrown

Respuesta

14

Josh G tenía la clave que corrigió este código: use RegisterName().

Tres beneficios aquí:

  1. No usa una variable miembro para salvar la referencia al cuadro de texto creado dinámicamente.
  2. Compilar.
  3. Código completo.

    using System; 
    using System.Windows; 
    using System.Windows.Controls; 
    
    namespace AddControlsDynamically 
    { 
        public partial class Window1 : Window 
        { 
         public void Window_Loaded(object sender, RoutedEventArgs e) 
         { 
          GenerateControls(); 
         } 
         public void GenerateControls() 
         { 
          Button btnClickMe = new Button(); 
          btnClickMe.Content = "Click Me"; 
          btnClickMe.Name = "btnClickMe"; 
          btnClickMe.Click += new RoutedEventHandler(this.CallMeClick); 
          someStackPanel.Children.Add(btnClickMe); 
          TextBox txtNumber = new TextBox(); 
          txtNumber.Name = "txtNumber"; 
          txtNumber.Text = "1776"; 
          someStackPanel.Children.Add(txtNumber); 
          someStackPanel.RegisterName(txtNumber.Name, txtNumber); 
         } 
         protected void CallMeClick(object sender, RoutedEventArgs e) 
         { 
          TextBox txtNumber = (TextBox) this.someStackPanel.FindName("txtNumber"); 
          string message = string.Format("The number is {0}", txtNumber.Text); 
          MessageBox.Show(message); 
         } 
        } 
    } 
    
+0

Esto funciona bastante bien. Estoy cambiando esto a la respuesta aceptada porque hace lo que originalmente quería. El otro también funciona bien, pero no quería crear un cuadro de texto y almacenarlos. –

2

¿Hay alguna forma se puede hacer del control del cuadro de texto en un campo de su clase en lugar de una variable dentro de su método de generador de

public class MyWindow : Window 
{ 
    private TextBox txtNumber; 

    public void Window_Loaded() 
    { 
     GenerateControls(); 
    } 

    public void GenerateControls() 
    { 
     Button btnClickMe = new Button(); 
     btnClickMe.Content = "Click Me"; 
     btnClickMe.Name = "btnClickMe"; 
     btnClickMe.Click += new RoutedEventHandler(this.CallMeClick); 
     someStackPanel.Childern.Add(btnClickMe); 
     txtNumber = new TextBox(); 
     txtNumber.Name = "txtNumber"; 
     txtNumber.Text = "1776"; 
     someStackPanel.Childern.Add(txtNumber); 
    } 

    protected void ClickMeClick(object sender, RoutedEventArgs e) 
    {  
     // Find the phone number  
     string message = string.Format("The number is {0}", txtNumber.Text);   
     MessageBox.Show(message); 
    } 
} 
+0

Esto funcionará. Sin embargo, ¿no hay forma de encontrarlo? ¿Qué sucede si tengo 10 cuadros de texto? ¿Es la solución para crear una lista y simplemente usar Linq para encontrarlas? –

+0

Acepté esta respuesta porque funciona, y si tengo 10 cuadros de texto, puedo crear una lista y encontrarlos en una lista. Gracias. –

+0

El código no se compila: Childern, CallMeClick no definido, etc. – hughdbrown

5

Otro método consiste en establecer el asociado TextBox como Button Tag cuando instanciando ellos.

btnClickMe.Tag = txtNumber; 

De esta manera se puede recuperar de nuevo en control de eventos.

protected void ClickMeClick(object sender, RoutedEventArgs e) 
{ 
    Button btnClickMe = sender as Button; 
    if (btnClickMe != null) 
    { 
     TextBox txtNumber = btnClickMe.Tag as TextBox; 
     // ... 
    } 
} 
+0

Esto también funciona. –

3

Si desea hacer una búsqueda exhaustiva a través del árbol visual de los controles, puede utilizar la clase VisualTreeHelper.

Utilice el siguiente código para iterar a través de todos los niños visuales de un control:

for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parentObj); i++) 
{ 
    DependencyObject child = VisualTreeHelper.GetChild(parent, i); 

    if (child is TextBox) 
     // Do something 
} 

Si desea buscar hacia abajo en el árbol, tendrá que llevar a cabo este bucle de forma recursiva, así:

public delegate void TextBoxOperation(TextBox box); 

public bool SearchChildren(DependencyObject parent, TextBoxOperation op) 
{ 
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) 
    { 
     DependencyObject child = VisualTreeHelper.GetChild(parent, i); 

     TextBox box = child as TextBox; 

     if (box != null) 
     { 
      op.Invoke(box); 
      return true; 
     } 

     bool found = SearchChildren(child, op); 

     if (found) 
      return true; 
    } 
} 
4

Usted puede conseguir su controlador de clic originales a trabajar al registrar el nombre del cuadro de texto:

someStackPanel.RegisterName(txtNumber.Name, txtNumber); 

Esto permitirá que llame FindName en el StackPanel y encontrar el cuadro de texto .

Cuestiones relacionadas