2010-02-18 4 views
27

FindName сломана для меня :(WPF - FindName Возвращает пустое значение, когда оно не должно

Если вы являетесь экспертом в таких вещах, которые я хотел бы некоторую помощь

Объект Я ищу там.. у меня есть доказательство

Вот сценарий:.

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

popup равна нулю, но не всегда просто иногда но даже тогда, когда он установлен в нуль ребенка я являюсь Looki.. ng для есть.

Я поставил точку останова, когда он был пустым, и схватил эти два скриншота.

где FindName возвращается нуль для "popSelectIteration":

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

Но если покопаться в часы, вы видите, что ребенок есть:

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

Так что я пропущу? Почему FindName не находит его? Как видно из снимка экрана, это не проблема времени (часы FindName имеют значение NULL, но прямой путь в порядке).

Есть ли лучший способ найти контроль?

Боковое примечание: Если вы заинтересованы в XAML для соответствующей кнопки переключения, вы можете найти в этом вопросе: WPF - FrameworkElement - Enumerate all decendents?.


Update: Я сделал некоторые копать, чтобы понять, почему это не удается несколько раз и в других случаях это работает. У меня есть анимация, которая вызывает NameScope.SetNameScope((DependencyObject)form, new NameScope()); (Полный код метода here). Сразу после этого вызов FindName начинает сбой.

Я действительно не понимаю этого звонка. Кажется, я скопировал и вставил код. Во всяком случае, я прокомментировал это. Но я хотел бы знать, почему это не удается.

ответ

30

Я бы предположил, что это связано с различием между визуальным и логическим деревом. Элемент управления находится в логическом дереве, но, возможно, шаблон для этого элемента управления еще не применен, и поэтому FindName не вернет ничего полезного.

Вы можете попытаться вызвать ApplyTemplate(); на контейнере.

Это также объясняет, почему оно иногда что-то возвращает.

+0

Работал для меня. Имела эту проблему с Template.FindName() – Trap

+0

Это сработало для меня, это была проблема больше для элементов управления, которые были скрыты изначально или на вкладке, которая изначально не была видимой. – Dave

+0

У меня возникла проблема с GetTemplateChild ("PART_EditableTextBox") с помощью ComboBox. Вызов ApplyTemplate() заранее решил проблему. Благодаря! –

1

Я предлагаю избегать использования функции FindName, основанной на моем опыте, особенно проблематично, когда вы пытаетесь найти что-то в DataTemplate, примененном к некоторому элементу управления. Вместо этого, если это возможно (на основе вашей архитектуры программного обеспечения), объявите всплывающее окно в XAML и ссылайтесь на него как на ресурс или используйте Binding, чтобы установить для него свойство Model. Удачи.

28

Попробуйте

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

Это просто со мной! я трачу на него 2 часа, наконец, я пробую ваш метод и работает !!! – Cheung

-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;» всегда будет возвращать нуль, причина явно: дата-объект еще не был применен до того, как вызывается OnApplyTemplate !!!!!!! поэтому ваш вопрос должен быть тем же! удачи!

5

По моему опыту, это происходит, когда вы добавляете элементы через код. Я обнаружил, что вы можете обмануть FindName() (или рамки анимации) через области имен. То есть, когда вы создаете свой контроль, вы

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

Для этого, чтобы надежно работать, хотя, вы должны убедиться, что вы разрегистрировать имя:

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

отправляю это в будущем.

Смежные вопросы