c# - WPF-FindName Devuelve nulo cuando no debería
(6)
En mi experiencia, esto sucede cuando agrega elementos a través del código subyacente. Descubrí que puedes engañar a FindName()
(o al marco de animación) a través de los ámbitos de nombres. Es decir, cuando creas tu control, lo haces.
NameScope.GetNameScope(yourContainer).RegisterName("name of your control", yourControlInstance);
Sin embargo, para que esto funcione de manera confiable, debe asegurarse de cancelar el registro del nombre:
NameScope.GetNameScope(yourContainer).UnregisterName("name of your control");
Publicar esto para futuras referencias.
FindName está roto para mí :(
Si eres un experto en tales cosas, me encantaría un poco de ayuda.
El objeto que busco está ahí. Tengo pruebas.
Aquí está el escenario:
ToggleButton button = (ToggleButton)sender;
Popup popup = (Popup)button.FindName("popSelectIteration");
popup
es nula pero no siempre. Solo a veces. Pero incluso cuando está configurado para anular el niño que busco está ahí.
Puse un punto de ruptura cuando era nulo y tomé estas dos capturas de pantalla.
El es donde FindName devuelve nulo para "popSelectIteration":
texto alt http://img175.imageshack.us/img175/2055/popupisnull.png
Pero si te metes en el reloj, ves que el niño está allí:
texto alt http://img708.imageshack.us/img708/8757/watchwithpopupnull.png
Entonces, ¿qué me estoy perdiendo? ¿Por qué no lo encuentra FindName? Como puede ver en la captura de pantalla, esto no es un problema de tiempo (el reloj FindName es nulo pero la ruta directa está bien).
¿Hay una mejor manera de encontrar un control?
Nota al margen: Si está interesado en el XAML para el botón de alternar en cuestión, puede encontrarlo en esta pregunta: WPF - FrameworkElement - ¿Enumerar todos los decendentes? .
Actualización : hice algunas excavaciones 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.
Intente utilizar button.FindResource("popSelectIteration")
Me he encontrado con la misma pregunta ahora, pero uso el método como el siguiente:
#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 de creación dinámica y cuyo contenedor o "Contenedor" se oculta o se contrae, el código "this.PART_ListViewLeft = GetTemplateChild (cPART_ListViewLeft) como ListView;" siempre se devolverá nulo, la razón es clara: el datatemplete aún no se ha aplicado antes de que se llame a OnApplyTemplate !!!!!!! entonces tu pregunta debe ser la misma !! ¡buena suerte!
Sugiero evitar el uso de la función FindName, según mi experiencia, especialmente problemática cuando intenta encontrar algo en el DataTemplate aplicado a algún control. En su lugar, si es posible (según su arquitectura de software), declare el Popup en XAML y consúltelo como recurso o use el enlace para establecer alguna propiedad del modelo como referencia. Buena suerte.
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 quizás la plantilla para este control aún no se haya aplicado y, por lo tanto, FindName no devolverá nada útil.
Podría intentar llamar a ApplyTemplate (); en el contenedor primero.
Esto también explicaría por qué devuelve algo a veces.
Tratar
LogicalTreeHelper.FindLogicalNode(button, "popSelectIteration");