为什么我不能使用FindName()按名称访问TextBox?

Edw*_*uay 6 c# wpf xaml textbox

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

XAML:

<Window x:Class="TestDynamicTextBox343.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel>
        <Border >

            <DockPanel x:Name="FormBase" LastChildFill="True">

            </DockPanel>

        </Border>

        <Button Content="Save" Click="Button_Click"/>
    </StackPanel>
</Window>
Run Code Online (Sandbox Code Playgroud)

代码背后:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

答案补遗:

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

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

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

void RegisterControl<T>(string textBoxName, T textBox)
{
    if ((T)this.FindName(textBoxName) != null)
        this.UnregisterName(textBoxName);
    this.RegisterName(textBoxName, textBox);
}
Run Code Online (Sandbox Code Playgroud)

bru*_*nde 15

这与WPF XAML Namescopes有关.

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

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

        this.RegisterName("FirstName", textBox);
        ...
Run Code Online (Sandbox Code Playgroud)

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

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