Почему я не могу получить доступ к TextBox по имени с помощью FindName()?
Почему 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>
Код позади:
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);
}
Или, если вы будете регистрировать что-либо кроме TextBoxes, универсальная версия:
void RegisterControl<T>(string textBoxName, T textBox)
{
if ((T)this.FindName(textBoxName) != null)
this.UnregisterName(textBoxName);
this.RegisterName(textBoxName, textBox);
}
1 ответ
Это связано с именными областями WPF XAML.
Поскольку вы добавляете элементы в проанализированные деревья элементов, вам нужно вызвать RegisterName
,
...
TextBox textBox = new TextBox();
textBox.Name = "FirstName";
textBox.Text = "test";
this.RegisterName("FirstName", textBox);
...
Добавление элементов в деревья проанализированных элементов
Любые дополнения к дереву элементов после начальной загрузки и обработки должны вызывать соответствующую реализацию RegisterName для класса, который определяет область имен XAML. В противном случае на добавленный объект нельзя ссылаться по имени через такие методы, как FindName. Простая установка свойства Name (или атрибута x:Name) не регистрирует это имя ни в какой области имен XAML. Добавление именованного элемента в дерево элементов с именной областью XAML также не регистрирует имя в именной области XAML. Хотя именные области XAML могут быть вложенными, вы обычно регистрируете имена в именной области XAML, которая существует в корневом элементе, так что ваше местоположение именной области XAML совпадает с именной областью XAML, которая была бы создана на эквивалентной загруженной странице XAML. Наиболее распространенный сценарий для разработчиков приложений заключается в том, что вы будете использовать RegisterName для регистрации имен в именной области XAML в текущем корне страницы. RegisterName является частью одного важного сценария поиска раскадровок, которые будут работать как анимация. Для получения дополнительной информации см. Обзор раскадровки. Если вы вызываете RegisterName для элемента, отличного от корневого элемента в том же дереве объектов, имя по-прежнему регистрируется для элемента, ближайшего к корню, как если бы вы вызывали RegisterName для корневого элемента.