Подтвердить что ты не робот

WPF - FindName Возвращает null, когда он не должен

FindName для меня нарушен: (

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

Объект, который я ищу, есть. У меня есть доказательство.

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

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

popup имеет значение null, но не всегда. Просто иногда. Но даже если для него установлено значение null, я ищу его.

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

Это где FindName возвращает значение null для "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 - Перечислить все декомпоненты?.


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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Попробуйте

LogicalTreeHelper.FindLogicalNode(button, "popSelectIteration");

Ответ 3

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

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

Чтобы это было надежно работать, вы должны убедиться, что вы отменили регистрацию имени:

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

Публикуйте это для справок в будущем.

Ответ 4

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

Ответ 5

У меня есть тот же вопрос, но я использую метод, как показано ниже:

    #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!!!!!!!  так что ваш вопрос должен быть одним и тем же! удачи!

Ответ 6

Попробуйте использовать button.FindResource("popSelectIteration")