2010-02-18 80 views
27

FindName被打破了我:(WPF - FindName當它不應該

如果你是這樣的事情一個專家我喜歡一些幫助,則返回null

我找的對象是存在的。我有證據

下面是這種情況:

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

popup爲空,但並不總是公正,但有時即使它被設置爲null我looki孩子。在那裏。

我把一個斷點當它爲空,並抓住這兩個截圖。

的就是FindName將返回空值 「popSelectIteration」:

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

但如果你深入到手錶,你看到孩子有:

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

那麼我錯過了什麼?爲什麼FindName找不到它?從屏幕截圖中可以看到,這不是一個計時問題(FindName手錶爲空,但直接路徑正常)。

有沒有更好的方法來找到控件?

邊注意:如果您在XAML中插入問題的切換按鈕,可以在此問題中找到它:WPF - FrameworkElement - Enumerate all decendents?


更新:我做了一些挖掘,看看爲什麼失敗了一些時間,其他時間它的作品。我有一個動畫,調用NameScope.SetNameScope((DependencyObject)form, new NameScope());(完整方法代碼here)。在調用之後,FindName開始失敗。

我真的不明白那個電話。我想我複製並粘貼了代碼。無論如何,我評論它。但我想知道爲什麼這是失敗的。

回答

30

我猜想它與視覺樹和邏輯樹之間的差異有關。該控件位於邏輯樹中,但該控件的模板可能尚未應用,因此FindName不會返回任何有用的內容。

你可以嘗試調用ApplyTemplate();首先在容器上。

這也可以解釋爲什麼它有時會返回一些東西。

+0

爲我工作。這個問題與Template.FindName() – Trap 2011-11-13 02:46:03

+0

這對我來說,這是一個問題更多的控件,最初隱藏或最初不可見的選項卡上。 – Dave 2012-06-30 14:38:07

+0

我在使用ComboBox時遇到GetTemplateChild(「PART_EditableTextBox」)問題。事先調用ApplyTemplate()可以解決問題。謝謝! – 2014-05-14 14:05:28

1

我建議避免使用FindName函數,根據我的經驗,特別是當你嘗試在DataTemplate中找到某些應用於某個控件的問題時。 相反,如果可能(基於您的軟件體系結構)聲明XAML中的Popup並將其稱爲資源或使用Binding將某些Model屬性設置爲其引用。 祝你好運。

28

嘗試

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

它恰好發生在我身上!我花了2個小時,最後,我嘗試你的方法和作品! – Cheung 2014-01-28 17:39:01

-1

嘗試使用button.FindResource("popSelectIteration")

1

我現在已經達到了同樣的問題,但我使用如下的方法:

#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 

如果控件是動態創建和其中或者其容器的「可見性」設置爲隱藏或摺疊,則代碼「this.PART_ListViewLeft = GetTemplateChild(cPART_ListViewLeft)爲ListView;」將始終返回null,原因很明顯:在調用OnApplyTemplate之前,數據完整尚未應用!!!!!!! 所以你的問題應該是同一個! 祝你好運!

5

以我的經驗,當你通過代碼隱藏添加項目時會發生這種情況。我發現你可以通過名稱範圍欺騙FindName()(或動畫框架)。也就是說,當你創建你的控制,你做

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

對於這個可靠地工作,但是,你必須確保你註銷名稱:

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

發佈此以供將來參考。