WPF - FindName不应该返回null

时间:2010-02-18 00:27:53

标签: c# wpf findname

FindName对我来说是破碎的:(

如果你是这方面的专家,我会很乐意帮助你。

我正在寻找的对象就在那里。我有证据。

以下是该方案:

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

popup为空,但并非总是如此。只是有时候。但即使它被设置为null,我正在寻找的孩子就在那里。

我在它为空时设置了一个断点并抓住了这两个截图。

FindName为“popSelectIteration”返回null的位置:

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开始失败。

我真的不明白这个电话。我想我复制并粘贴了代码。无论如何,我评论了它。但我很想知道为什么会失败。

8 个答案:

答案 0 :(得分:34)

我猜它与视觉树和逻辑树之间的区别有关。控件位于逻辑树中,但可能尚未应用此控件的模板,因此FindName不会返回任何有用的内容。

您可以尝试调用ApplyTemplate();首先在容器上。

这也可以解释为什么它有时会返回一些东西。

答案 1 :(得分:32)

尝试

LogicalTreeHelper.FindLogicalNode(button, "popSelectIteration");

答案 2 :(得分:6)

根据我的经验,当您通过代码隐藏添加项目时会发生这种情况。我发现你可以通过名称范围欺骗FindName()(或动画框架)。也就是说,当你创建控件时,你可以

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

为了使其可靠地工作,您必须确保取消注册名称:

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

发布此信息以供将来参考。

答案 3 :(得分:2)

我现在遇到了同样的问题,但我使用的方法如下:

    #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之前尚未应用datatemplete !!!!!!!    所以你的问题应该是同一个!! 祝你好运!

答案 4 :(得分:1)

我建议根据我的经验避免使用FindName函数,当您尝试在DataTemplate中找到应用于某些控件的内容时,尤其有问题。 相反,如果可能(基于您的软件架构)在XAML中声明Popup 像资源一样引用它或使用Binding将一些Model属性设置为它的引用。 祝你好运。

答案 5 :(得分:0)

ellipseStoryboard.Children.Add(myRectAnimation);         containerCanvas.Children.Add(myPath); 添加后,注册控件 RegisterName(“ TextBlock1”,Var_TextBox); 要么 RegisterName(myRectAnimation.Name,myRectAnimation); RegisterName(myPath.Name,myPath);

答案 6 :(得分:0)

聚会晚一点(实际上并没有回答OP问题),但是

动态添加元素时,FindName无法找到它们。 您需要通过致电RegisterName进行注册。

示例:

Button myButton = new Button();
myButton.Content = generateNumber();
myButton.Name = "button_" + generateNumber;

RegisterName(myButton.Name, myButton);

Panel.Children.Add(myButton);
object o = Panel.FindName(myButton.Name);

也许有人会觉得有用。

答案 7 :(得分:-1)

尝试使用button.FindResource("popSelectIteration")