为什么我无法通过FindName()按名称访问TextBox?

6
在下面的示例中,为什么FindName()返回nullXAML:
<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>

后台代码:

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

答案补充:

非常感谢,Bruno,这很有效。为了不重复添加相同的名称,我用以下方式进行包装:

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

如果您要注册除文本框以外的任何内容,可以使用通用版本:

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

15

这与 WPF XAML 命名空间 相关。

因为你要向已解析的元素树中添加元素,所以需要调用RegisterName方法。

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

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

向已解析元素树添加元素

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


1
我不确定是否应该使用FindName()函数注册我想要查找的所有名称。我应该吗? - Lorenzo Sciuto
@LorenzoSciuto 仅限于你需要的那些,特别是那些将被动画定位的元素。 - Sabuncu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接