为什么我不能用FindName()访问一个文本框?

时间:2021-06-25 21:11:04

Why does FindName() return null in the following example?

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

XAML:

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>

Code Behind:

背后的代码:

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

Addendum to Answer:

Thanks a lot, Bruno, that worked well. In order not to add the same name twice, I wrap it with this:

谢谢你,布鲁诺,你做得很好。为了避免两次添加相同的名字,我用这个来包装:

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

Or if you will be registering anything other than TextBoxes, a generic version:

或者如果你要注册除了文本框以外的任何东西,一个通用的版本:

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

1 个解决方案

#1


15  

This is related to WPF XAML Namescopes.

这与WPF XAML Namescopes有关。

Because you add elements to parsed element trees, you need to call RegisterName.

因为您在解析元素树中添加元素,所以需要调用RegisterName。

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

        this.RegisterName("FirstName", textBox);
        ...

Adding Elements to Parsed Element Trees

在解析元素树中添加元素。

Any additions to the element tree after initial loading and processing must call the appropriate implementation of RegisterName for the class that defines the XAML namescope. Otherwise, the added object cannot be referenced by name through methods such as FindName. Merely setting a Name property (or x:Name Attribute) does not register that name into any XAML namescope. Adding a named element to an element tree that has a XAML namescope also does not register the name to the XAML namescope. Although XAML namescopes can be nested, you generally register names to the XAML namescope that exists on the root element, so that your XAML namescope location parallels the XAML namescope that would have been created in an equivalent loaded XAML page. The most common scenario for application developers is that you will use RegisterName to register names into the XAML namescope on the current root of the page. RegisterName is part of one important scenario for finding storyboards that will run as animations. For more information, see Storyboards Overview. If you call RegisterName on an element other than the root element in the same object tree, the name is still registered to the element nearest the root, as if you had called RegisterName on the root element.

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

#1


15  

This is related to WPF XAML Namescopes.

这与WPF XAML Namescopes有关。

Because you add elements to parsed element trees, you need to call RegisterName.

因为您在解析元素树中添加元素,所以需要调用RegisterName。

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

        this.RegisterName("FirstName", textBox);
        ...

Adding Elements to Parsed Element Trees

在解析元素树中添加元素。

Any additions to the element tree after initial loading and processing must call the appropriate implementation of RegisterName for the class that defines the XAML namescope. Otherwise, the added object cannot be referenced by name through methods such as FindName. Merely setting a Name property (or x:Name Attribute) does not register that name into any XAML namescope. Adding a named element to an element tree that has a XAML namescope also does not register the name to the XAML namescope. Although XAML namescopes can be nested, you generally register names to the XAML namescope that exists on the root element, so that your XAML namescope location parallels the XAML namescope that would have been created in an equivalent loaded XAML page. The most common scenario for application developers is that you will use RegisterName to register names into the XAML namescope on the current root of the page. RegisterName is part of one important scenario for finding storyboards that will run as animations. For more information, see Storyboards Overview. If you call RegisterName on an element other than the root element in the same object tree, the name is still registered to the element nearest the root, as if you had called RegisterName on the root element.

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