2010-02-18 5 views
27

Findname für mich kaputt ist :(WPF - Findname Gibt null zurück, wenn es nicht

Wenn Sie ein Experte in solchen Dingen sind, würde ich etwas Hilfe lieben

Das Objekt Ich suche da ist.. ich habe Beweise

Hier ist das Szenario:.

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

popup null ist aber nicht immer einfach manchmal aber auch, wenn es gesetzt ist, das Kind auf null ich bin looki.. ng für ist da.

Ich legte einen Punkt in, wenn es Null war und griff diese zwei Screenshots.

Das ist, wo Findname null für "popSelectIteration" kehrt zurück:

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

Aber wenn man in die Uhr graben, sehen Sie, dass das Kind gibt es:

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

Also was fehlt mir? Warum findet FindName es nicht? Wie Sie aus dem Screenshot sehen können, ist dies kein Timing-Problem (die FindName-Uhr ist null, aber der direkte Pfad ist in Ordnung).

Gibt es eine bessere Möglichkeit, ein Steuerelement zu finden?

Seitennotiz: Wenn Sie im XAML für den betreffenden Umschaltknopf interessiert sind, finden Sie in dieser Frage: WPF - FrameworkElement - Enumerate all decendents?.


aktualisieren: Ich habe einige zu sehen, graben, warum dies einige Male und zu anderen Zeiten nicht funktioniert. Ich habe eine Animation, die NameScope.SetNameScope((DependencyObject)form, new NameScope()); aufruft (Vollständige Methode Code here). Gleich nach diesem Aufruf beginnt der FindName fehlzuschlagen.

Ich verstehe diesen Anruf wirklich nicht. Ich glaube, ich habe den Code kopiert und eingefügt. Wie auch immer, ich habe es auskommentiert. Aber ich würde gerne wissen, warum das scheitert.

Antwort

30

Ich denke, es hat mit dem Unterschied zwischen dem visuellen und logischen Baum zu tun. Das Steuerelement befindet sich in der logischen Struktur, aber möglicherweise wurde die Vorlage für dieses Steuerelement noch nicht angewendet und daher wird FindName nichts nützliches zurückgeben.

Sie könnten versuchen, ApplyTemplate() aufzurufen; zuerst auf den Behälter.

Dies würde auch erklären, warum es manchmal etwas zurückgibt.

+0

Arbeitete für mich. War dieses Problem mit Template.FindName() – Trap

+0

Dies funktionierte für mich, es war ein Problem mehr für Steuerelemente, die ursprünglich oder auf einer Registerkarte ausgeblendet wurden, die ursprünglich nicht sichtbar war. – Dave

+0

Ich hatte ein Problem mit GetTemplateChild ("PART_EditableTextBox") mit einer ComboBox. Durch den Aufruf von ApplyTemplate() wurde das Problem behoben. Vielen Dank! –

1

Ich würde vorschlagen, zu vermeiden, FindName-Funktion, basierend auf meiner Erfahrung, besonders problematisch, wenn Sie versuchen, etwas in der DataTemplate auf ein Steuerelement angewendet zu finden. Wenn es möglich ist (basierend auf Ihrer Softwarearchitektur), deklarieren Sie Popup in XAML und verweisen Sie darauf wie Ressource oder verwenden Sie Binding, um eine Model-Eigenschaft auf ihre Referenz zu setzen. Viel Glück.

28

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

Es passiert mir einfach! ich verbringe 2 Stunden damit, schliesslich probiere ich deine Methode aus und arbeite !!! – Cheung

-1

Try Try button.FindResource("popSelectIteration")

1

Ich treffe jetzt die gleiche Frage haben zu verwenden, aber ich benutze das Verfahren wie folgt:

#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 

, wenn die Steuerung dynamisch erstellen und von welchem ​​Container oder dessen Container die Sichtbarkeit auf Ausblenden oder Reduziert gesetzt ist, dann der Code "this.PART_ListViewLeft = GetTemplateChild (cPART_ListViewLeft) als ListView;" wird immer null zurückgeben, der Grund ist klar: der Datamomplete wurde noch nicht angewendet bevor OnApplyTemplate aufgerufen wird !!!!!!! so sollte Ihre Frage die gleiche sein !! viel Glück!

5

Meiner Erfahrung nach geschieht dies, wenn Sie Elemente über Code-Behind hinzufügen. Ich habe festgestellt, dass Sie FindName() (oder das Animationsframework) über Namensbereiche täuschen können. Das heißt, wenn Sie das Steuerelement erstellen, geben Sie

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

Für diese zuverlässig zu arbeiten, obwohl, müssen Sie sicherstellen, dass Sie den Namen deregistrieren:

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

dies für die Zukunft der Veröffentlichung.

Verwandte Themen