为什么我不能通过Name使用FindName()访问TextBox?

为什么FindName()在以下示例中返回null

XAML:

      

代码背后:

 using System; using System.Windows; using System.Windows.Controls; namespace TestDynamicTextBox343 { public partial class Window1 : Window { public Window1() { InitializeComponent(); StackPanel sp = new StackPanel(); sp.Orientation = Orientation.Horizontal; TextBlock textBlock = new TextBlock(); textBlock.Text = "First Name: "; TextBox textBox = new TextBox(); textBox.Name = "FirstName"; textBox.Text = "test"; sp.Children.Add(textBlock); sp.Children.Add(textBox); FormBase.Children.Add(sp); } private void Button_Click(object sender, RoutedEventArgs e) { TextBox tb = (TextBox)this.FindName("FirstName"); Console.WriteLine(tb.Text); } } } 

答案补遗:

非常感谢,布鲁诺,效果很好。 为了不两次添加相同的名称,我用它包装:

 void RegisterTextBox(string textBoxName, TextBox textBox) { if ((TextBox)this.FindName(textBoxName) != null) this.UnregisterName(textBoxName); this.RegisterName(textBoxName, textBox); } 

或者,如果您要注册除TextBox之外的任何内容,则为通用版本:

 void RegisterControl(string textBoxName, T textBox) { if ((T)this.FindName(textBoxName) != null) this.UnregisterName(textBoxName); this.RegisterName(textBoxName, textBox); } 

这与WPF XAML Namescopes有关 。

因为您向已解析的元素树添加元素,所以需要调用RegisterName

  ... TextBox textBox = new TextBox(); textBox.Name = "FirstName"; textBox.Text = "test"; this.RegisterName("FirstName", textBox); ... 

向已解析的元素树添加元素

初始加载和处理后对元素树的任何添加都必须为定义XAML名称范围的类调用RegisterName的相应实现。 否则,添加的对象不能通过FindName等方法按名称引用。 仅设置Name属性(或x:Name Attribute)不会将该名称注册到任何XAML名称范围中。 将命名元素添加到具有XAML名称范围的元素树也不会将名称注册到XAML名称范围。 虽然可以嵌套XAML名称范围,但通常将名称注册到根元素上存在的XAML名称范围,以便您的XAML名称范围位置与在等效加载的XAML页面中创建的XAML名称范围平行。 应用程序开发人员最常见的情况是,您将使用RegisterName将名称注册到页面当前根目录的XAML名称范围中。 RegisterName是查找将作为动画运行的故事板的一个重要场景的一部分。 有关更多信息,请参阅故事板概述。 如果在同一对象树中的根元素之外的元素上调用RegisterName,则该名称仍会注册到离根最近的元素,就像您在根元素上调用了RegisterName一样。