WPF ¿Cómo se crea un cuadro de texto de forma dinámica y encontrar el cuadro de texto en un botón de clic?

StackOverflow https://stackoverflow.com/questions/537073

Pregunta

Estoy creando un TextBox y una Button dinámicamente usando el siguiente código:

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

conecto a un evento de clic al botón Click Me. El botón haga clic en mí, incluso se dispara correctamente. Sin embargo no puedo encontrar el TextBox entré en forma dinámica.

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 TextBox txtNumber?

¿Fue útil?

Solución

Josh G tenía la pista que fija este código:. Uso RegisterName ()

Tres beneficios aquí:

  1. No usa una variable miembro para salvar la referencia al cuadro de texto creado dinámicamente.
  2. Compila.
  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);
            }
        }
    }
    

Otros consejos

Otro método consiste en ajustar la TextBox asociado 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;
        // ...
    }
}

Usted puede conseguir su controlador de clic al trabajo original, al registrar el nombre del cuadro de texto:

someStackPanel.RegisterName(txtNumber.Name, txtNumber);

Esto entonces permitirá llamar FindName en el StackPanel y encontrar el cuadro de texto.

Si usted quiere 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 hijos de un control visual:

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

¿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

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);
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top