2009-11-19 6 views
5

Así que en el código de ejemplo siguiente, creo un UserControl UserControldChild que es un elemento secundario de la ventana principal, Window1.xaml. ¿Por qué el método FindName() no puede encontrar el "myButton" en el siguiente código?¿Por qué Window.FindName() no descubre la x: Nombre de un botón en un Child UserControl? ¿Cómo funcionan los NameScopes?

Esto tiene que ver con el WPF XAML NameScopes, pero aún no he encontrado una buena explicación sobre cómo funciona NameScope. ¿Alguien me puede iluminar?

//(xml) Window1.xaml  
<Window x:Class="VisualTreeTestApplication.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:VisualTreeTestApp="clr-namespace:VisualTreeTestApplication" 
    Title="Window1" Height="400" Width="400"> 
    <Grid> 
     <VisualTreeTestApp:UserControlChild/> 
    </Grid> 
</Window> 

//(c#) Window1.xaml.cs 
namespace VisualTreeTestApplication 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
    public Window1() 
    { 
     InitializeComponent(); 
     Button btnTest = (Button)Application.Current.MainWindow.FindName("myButton"); 
     // btnTest is null! 
    } 
    } 
} 

control de usuario a continuación:

//(wpf) UserControlChild.xaml 
<UserControl x:Class="VisualTreeTestApplication.UserControlChild" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="300" Width="300"> 
    <Grid x:Name="myGrid">  
     <Button x:Name="myButton" Margin="20" >Button</Button> 
    </Grid> 
</UserControl> 

//(c#) UserControlChild.xaml.cs (no changes) 
namespace VisualTreeTestApplication 
{ 
    /// <summary> 
    /// Interaction logic for UserControlChild.xaml 
    /// </summary> 
    public partial class UserControlChild : UserControl 
    { 
    public UserControlChild() 
    { 
     InitializeComponent(); 
    } 
    } 
} 

En caso de que esto no es respondida correctamente, he encontrado una alternativa al uso FindName() documentado in the post here.

Respuesta

5

Tiene razón, esto tiene que ver con los nombres de XAML.

Esto está (algo mal) documentado en el Name related APIs section of the XAML Namescopes page.

Básicamente, si tiene un FrameworkElement o FrameworkContentElement, definirá su propio alcance de nombre. Si llama a FindName() en un tipo que no tiene un namescope, WPF busca hasta hasta que encuentre un elemento que defina un namescope, luego busca dentro de ese namescope.

En su caso, está buscando en el namescope de Window (es un FrameworkContentElement, por lo que define su propio alcance). Simplemente busca elementos definidos en ese alcance.

En su caso, el botón está en el namescope UserControl, por lo que Window.FindName() no lo encuentra. No hay búsqueda automática abajo el árbol en ámbitos de nivel inferior.

Esto es una buena cosa: su "Ventana" no debe saber o quiere saber nada sobre los detalles internos de un UserControl que está usando. Si necesita propiedades dentro del UserControl, deberían estar expuestas a nivel de UserControl: deje que el control administre sus propios hijos.

+0

¡Gracias por la aclaración! Parece que FindName no sería la mejor herramienta para el trabajo en esta situación, también conocido como que no puede buscar fácilmente en el alcance. ¿Puede pensar en un mejor método para encontrar el nombre de un botón secundario en el árbol visual que no sea la solución recursiva que se detalla aquí? http://stackoverflow.com/questions/636383/wpf-ways-to-find-controls/1759923#1759923 – CrimsonX

Cuestiones relacionadas