WPF, как мне создать текстовое поле динамически и найти текстовое поле одним нажатием кнопки? - PullRequest
15 голосов
/ 11 февраля 2009

Я создаю TextBox и Button динамически, используя следующий код:

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

Я подключаюсь к событию щелчка к кнопке Click Me. Кнопка «Нажми меня» даже срабатывает правильно. Однако я не могу найти TextBox, который я ввел динамически.

Вот мое событие Click Me:

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

Как мне найти TextBox txtNumber?

Ответы [ 5 ]

15 голосов
/ 11 февраля 2009

Джош Джи понял, что исправил этот код: используйте RegisterName ().

Три преимущества здесь:

  1. Не использует переменную-член для сохранения ссылки на динамически создаваемый TextBox.
  2. компилировать.
  3. Полный код.

    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);
            }
        }
    }
    
5 голосов
/ 11 февраля 2009

Другой метод состоит в том, чтобы установить ассоциированный TextBox как Button Tag при их создании.

btnClickMe.Tag = txtNumber;

Таким образом, вы можете получить его обратно в обработчике событий.

protected void ClickMeClick(object sender, RoutedEventArgs e)
{
    Button btnClickMe = sender as Button;
    if (btnClickMe != null)
    {
        TextBox txtNumber = btnClickMe.Tag as TextBox;
        // ...
    }
}
4 голосов
/ 11 февраля 2009

Вы можете заставить свой оригинальный обработчик кликов работать, зарегистрировав имя текстового поля:

someStackPanel.RegisterName(txtNumber.Name, txtNumber);

Это позволит вам затем вызвать FindName на StackPanel и найти TextBox.

3 голосов
/ 11 февраля 2009

Если вы хотите выполнить всеобъемлющий поиск по визуальному дереву элементов управления, вы можете использовать класс VisualTreeHelper.

Используйте следующий код для перебора всех визуальных потомков элемента управления:

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

    if (child is TextBox)
        // Do something
}

Если вы хотите выполнить поиск вниз по дереву, вы захотите выполнить этот цикл рекурсивно, например так:

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;
    }
}
2 голосов
/ 11 февраля 2009

Есть ли способ, которым вы можете заставить TextBox управлять полем в вашем классе вместо переменной внутри вашего метода генератора

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...