次のコードを使用して、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
が見つかりません。
これが私のクリックミーイベントです:
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
を見つけるにはどうすればよいですか?
Josh Gには、このコードを修正する手がかりがありました。RegisterName()を使用してください。
ここでの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);
}
}
}
別の方法は、それらをインスタンス化するときに、関連付けられた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;
// ...
}
}
テキストボックスの名前を登録することで、元のクリックハンドラーを機能させることができます。
someStackPanel.RegisterName(txtNumber.Name, txtNumber);
これにより、StackPanelでFindNameを呼び出して、TextBoxを見つけることができます。
コントロールのビジュアルツリーを包括的に検索する場合は、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;
}
}
ジェネレーターメソッド内の変数の代わりに、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);
}
}