2009-11-18 15 views
6

¿Por qué FindName() devuelve nulo en el siguiente ejemplo?¿Por qué no puedo acceder a un cuadro de texto por nombre con FindName()?

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> 

código subyacente:

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

Adición de respuesta:

Muchas gracias, Bruno, que funcionaba bien. Con el fin de no añadir el mismo nombre dos veces, me envuelvo con esto:

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

O si vaya a registrar otra cosa que no sea cuadros de texto, una versión genérica:

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

Respuesta

15

Esto se relaciona con WPF XAML Namescopes .

Como agrega elementos a los árboles de elementos analizados, debe llamar al RegisterName.

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

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

añadir elementos a Parsed Elemento árboles

Cualquier adición a la árbol de elementos después de la carga y procesamiento inicial debe llamar a la apropiada aplicación de RegisterName para la clase que define la NameScope XAML . De lo contrario, el objeto agregado no puede ser al que se hace referencia por nombre a través de los métodos como FindName. Simplemente estableciendo una propiedad de nombre (o x: Nombre del atributo) no se registra ese nombre en ningún namescope XAML. Agregar un elemento con nombre a un árbol de elementos que tiene un namescope XAML tampoco registra el nombre en el namescope XAML. Aunque namescopes XAML se pueden anidar, que general registrar nombres en el XAML NameScope que existe en el elemento raíz , para que su NameScope XAML ubicación es paralela a la NameScope XAML que habría sido creado en una página XAML carga equivalente . El escenario común más para desarrolladores de aplicaciones es que usará RegisterName para registrar nombres en el namescope XAML en la raíz actual de la página. RegisterName es parte de un escenario importante para encontrar guiones gráficos que se ejecutarán como animaciones . Para obtener más información, consulte Descripción general de guiones gráficos. Si llama RegisterName en un elemento distinto el elemento raíz en el mismo árbol de objetos , el nombre está registrado todavía a el elemento más cercano a la raíz, como si hubiera llamado RegisterName en el elemento raíz.

+1

No recibí si debería registrar todos los nombres que quiero encontrar con la función FindName(). ¿Debería? –

+0

@LorenzoSciuto Solo aquellos que necesita, y específicamente los que serán el objetivo de la animación. – Sabuncu

Cuestiones relacionadas