2010-02-18 19 views
27

FindName se rompe para mí :(WPF - FindName devuelve NULL cuando no debería

Si usted es un experto en este tipo de cosas me gustaría un poco de ayuda

El objeto Busco está allí.. tengo pruebas

Aquí está el panorama:.

ToggleButton button = (ToggleButton)sender; 
Popup popup = (Popup)button.FindName("popSelectIteration"); 

popup es nulo, pero no siempre sólo a veces pero incluso cuando se establece en nulo el niño soy looki.. ng para está allí.

Puse un punto de ruptura cuando era nulo y capté estas dos capturas de pantalla.

El es donde FindName vuelve nulo para "popSelectIteration":

alt text http://img175.imageshack.us/img175/2055/popupisnull.png

Pero si usted cava en el reloj, se ve que el niño está ahí:

alt text http://img708.imageshack.us/img708/8757/watchwithpopupnull.png

Entonces, ¿qué me estoy perdiendo? ¿Por qué FindName no lo encuentra? Como puede ver en la captura de pantalla, este no es un problema de temporización (el reloj FindName es nulo, pero la ruta directa es correcta).

¿Hay una manera mejor de encontrar un control?

Nota al margen: Si usted intersted en el XAML para el botón de activación en cuestión se puede encontrar en esta pregunta: WPF - FrameworkElement - Enumerate all decendents?.


actualización: Hice algo de investigación para ver por qué esto falla algunas veces y otras veces funciona. Tengo una animación que llama a NameScope.SetNameScope((DependencyObject)form, new NameScope()); (código de método completo here). Justo después de esa llamada, FindName comienza a fallar.

Realmente no entiendo esa llamada. Creo que copié y pegué el código. De todos modos, lo comenté. Pero me encantaría saber por qué esto está fallando.

Respuesta

30

Supongo que tiene que ver con la diferencia entre el árbol visual y el lógico. El control está en el árbol lógico, pero tal vez la plantilla para este control no se haya aplicado todavía y, por lo tanto, FindName no devolverá nada útil.

Puede intentar llamar a ApplyTemplate(); en el contenedor primero.

Esto también explicaría por qué devuelve algo a veces.

+0

Funcionó para mí. Estaba teniendo este problema con Template.FindName() – Trap

+0

Esto funcionó para mí, era un problema más para los controles que estaban ocultos inicialmente o en una pestaña que no era visible inicialmente. – Dave

+0

Estaba teniendo un problema con GetTemplateChild ("PART_EditableTextBox") con un ComboBox. Llamar a ApplyTemplate() de antemano resolvió el problema. ¡Gracias! –

1

Sugiero evitar el uso de la función FindName, basado en mi experiencia, especialmente problemático cuando intenta encontrar algo en el DataTemplate aplicado a algún control. En cambio, si es posible (en función de la arquitectura de su software) declarar Popup en XAML y referirse a él como recurso o usar Enlace para establecer alguna propiedad del Modelo a su referencia. Buena suerte.

28

Trate

LogicalTreeHelper.FindLogicalNode(button, "popSelectIteration"); 
+1

¡Simplemente me sucede a mí! Pasé 2 horas en él, finalmente, ¡pruebo tu método y funciona! – Cheung

-1

intenta utilizar button.FindResource("popSelectIteration")

1

Tengo cumplir con la misma pregunta, pero yo uso el método, como a continuación:

#region Override - OnApplyTemplate 

    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     this.PART_ListViewLeft  = GetTemplateChild(cPART_ListViewLeft)  as ListView; 
     this.PART_ListViewCenter = GetTemplateChild(cPART_ListViewCenter) as ListView; 
     this.PART_ListViewRight  = GetTemplateChild(cPART_ListViewRight)  as ListView; 

     this.PART_GridViewLeft  = GetTemplateChild(cPART_GridViewLeft)  as DsxGridView; 
     this.PART_GridViewCenter = GetTemplateChild(cPART_GridViewCenter) as DsxGridView; 
     this.PART_GridViewRight  = GetTemplateChild(cPART_GridViewRight)  as DsxGridView; 
     if(this.PART_ListViewLeft!=null) 
      this.PART_ListViewLeft  .AlternationCount = this.AlternatingRowBrushes.Count; 
     if(this.PART_ListViewCenter!=null) 
      this.PART_ListViewCenter .AlternationCount = this.AlternatingRowBrushes.Count; 
     if(this.PART_ListViewRight!=null) 
      this.PART_ListViewRight  .AlternationCount = this.AlternatingRowBrushes.Count; 
     // ApplyTempleted = true; 
     CreateColumnLayout(); 
    } 
    #endregion 

si el control es dinámico crear y de los cuales o cuyo contenedor la 'Visibilidad' está configurada para ocultarse o Contraerse, entonces el código "this.PART_ListViewLeft = GetTemplateChild (cPART_ListViewLeft) como ListView;" devolverá null siempre, la razón es clara: el datatemplete aún no se ha aplicado antes de llamar a OnApplyTemplate !!!!!!! por lo que su pregunta debe ser la misma !! ¡buena suerte!

5

En mi experiencia, esto sucede cuando agrega elementos a través de código subyacente. Descubrí que puedes engañar FindName() (o el marco de animación) a través de los ámbitos de nombres. Es decir, cuando se crea su control, lo hace

NameScope.GetNameScope(yourContainer).RegisterName("name of your control", yourControlInstance); 

Para que esto funcione de forma fiable, sin embargo, usted debe asegurarse de que anula el registro del nombre:

NameScope.GetNameScope(yourContainer).UnregisterName("name of your control"); 

publicar esto para futuras referencias.

Cuestiones relacionadas