C# 为什么Window.FindName()不能在子用户控件中发现按钮的x:名称?又名命名空间是如何工作的?

C# 为什么Window.FindName()不能在子用户控件中发现按钮的x:名称?又名命名空间是如何工作的?,c#,wpf,user-controls,findname,C#,Wpf,User Controls,Findname,因此,在下面的示例代码中,我创建了一个UserControl UserControldChild,它是主窗口Window1.xaml的子窗口。为什么FindName()方法在下面的代码中找不到“myButton” 这一定和名称范围有关,但我还并没有找到一个关于名称范围如何工作的好解释。有人能启发我吗 //(xml) Window1.xaml <Window x:Class="VisualTreeTestApplication.Window1" xmlns="http://s

因此,在下面的示例代码中,我创建了一个UserControl UserControldChild,它是主窗口Window1.xaml的子窗口。为什么
FindName()
方法在下面的代码中找不到“myButton”

这一定和名称范围有关,但我还并没有找到一个关于名称范围如何工作的好解释。有人能启发我吗

//(xml) Window1.xaml    
<Window x:Class="VisualTreeTestApplication.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:VisualTreeTestApp="clr-namespace:VisualTreeTestApplication"
    Title="Window1" Height="400" Width="400">
    <Grid>
        <VisualTreeTestApp:UserControlChild/>
    </Grid>
</Window>

//(c#) Window1.xaml.cs
namespace VisualTreeTestApplication
{
  /// <summary>
  /// Interaction logic for Window1.xaml
  /// </summary>
  public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();
      Button btnTest = (Button)Application.Current.MainWindow.FindName("myButton");
      // btnTest is null!
    }
  }
}
/(xml)Window1.xaml
//(c#)Window1.xaml.cs
命名空间VisualTreestApplication
{
/// 
///Window1.xaml的交互逻辑
/// 
公共部分类Window1:Window
{
公共窗口1()
{
初始化组件();
Button btnTest=(Button)Application.Current.MainWindow.FindName(“myButton”);
//btnTest为空!
}
}
}
用户控制如下:

//(wpf) UserControlChild.xaml
<UserControl x:Class="VisualTreeTestApplication.UserControlChild"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid x:Name="myGrid">      
        <Button x:Name="myButton" Margin="20" >Button</Button>
    </Grid>
</UserControl>

//(c#) UserControlChild.xaml.cs (no changes)
namespace VisualTreeTestApplication
{
  /// <summary>
  /// Interaction logic for UserControlChild.xaml
  /// </summary>
  public partial class UserControlChild : UserControl
  {
    public UserControlChild()
    {
      InitializeComponent();
    }
  }
}
/(wpf)UserControlChild.xaml
按钮
//(c#)UserControlChild.xaml.cs(无更改)
命名空间VisualTreestApplication
{
/// 
///UserControlChild.xaml的交互逻辑
/// 
公共部分类UserControlChild:UserControl
{
公共UserControlChild()
{
初始化组件();
}
}
}

如果这个问题没有得到正确的回答,我找到了使用FindName()的替代方法

你是对的-这与XAML名称示波器有关

这一点(有点糟糕)记录在

基本上,如果您有一个FrameworkElement或FrameworkContentElement,它将定义自己的名称范围。如果对没有名称范围的类型调用FindName(),WPF将搜索树,直到找到定义名称范围的元素,然后在该名称范围内搜索

在您的例子中,它在窗口的名称范围中搜索(它是一个FrameworkContentElement,所以它定义了自己的范围)。它只搜索在该范围内定义的元素

在您的例子中,按钮位于UserControl的名称范围中,因此Window.FindName()找不到它。没有自动向下搜索树到较低级别范围的功能


这是一件好事——您的“窗口”不应该知道或不想知道它所使用的用户控件的任何内部细节。如果您需要UserControl中的属性,它们应该在UserControl级别公开-让控件管理自己的子项。

感谢您的澄清!在这种情况下,FindName似乎不是工作的最佳工具,也就是说,你不能轻易地在范围内搜索。除了这里详细介绍的递归解决方案之外,您能想出一种更好的方法来在可视化树中查找子按钮的名称吗?