WPF comment puis-je créer une zone de texte dynamique et de trouver la zone de texte sur un bouton clic?

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

Question

Je crée un TextBox et un Button dynamiquement en utilisant le code suivant:

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

Je HOO à un événement de clic sur le bouton Click Me. Le clic me touche même est tiré correctement. Cependant, je ne peux pas trouver le TextBox je suis entré dynamiquement.

Voici mon me cliquent sur l'événement:

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

Comment puis-je trouver le TextBox de txtNumber?

Était-ce utile?

La solution

Josh G avait la moindre idée qui a fixé ce code:. RegisterName utilisation ()

Trois avantages ici:

  1. N'utilise pas une variable membre pour enregistrer la référence à la zone de texte créé dynamiquement.
  2. Compile.
  3. Code complet.

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

Autres conseils

Une autre méthode consiste à définir la TextBox associée comme Button Tag lors de leur instanciation.

btnClickMe.Tag = txtNumber;

De cette façon, vous pouvez le récupérer en arrière dans le gestionnaire d'événements.

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

Vous pouvez obtenir votre gestionnaire de clic d'origine au travail en vous inscrivant le nom de la zone de texte:

someStackPanel.RegisterName(txtNumber.Name, txtNumber);

Cela vous permettra d'appeler FindName sur le StackPanel et de trouver la zone de texte.

Si vous voulez faire une recherche exhaustive dans l'arborescence visuelle des contrôles, vous pouvez utiliser la classe VisualTreeHelper.

Utilisez le code suivant pour itérer tous les enfants d'un contrôle visuel:

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

    if (child is TextBox)
        // Do something
}

Si vous voulez rechercher vers le bas dans l'arbre, vous voulez effectuer cette boucle récursive, comme suit:

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

Est-il possible que vous pouvez faire contrôler la zone de texte un champ dans votre classe au lieu d'une variable à l'intérieur de votre méthode de générateur

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);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top