c# - 为什么 Window.FindName() 不发现 x :Name of a button in a child UserControl? AKA NameScopes 如何工作?

标签 c# wpf user-controls findname

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

这一定与 WPF XAML NameScopes 有关,但我还没有找到关于 NameScope 如何工作的很好的解释。有人可以启发我吗?

//(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!
    }
  }
}

下面的用户控件:

//(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();
    }
  }
}

如果这个问题没有得到正确回答,我找到了使用 FindName() 的替代方法,记录在案 in the post here .

最佳答案

您是对的 - 这与 XAML 名称范围有关。

这在 Name related APIs section of the XAML Namescopes page 中有(有些不完善)记录.

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

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

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

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

关于c# - 为什么 Window.FindName() 不发现 x :Name of a button in a child UserControl? AKA NameScopes 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1764364/

相关文章:

c# - 连接的服务组件 Microsoft WCF Web 服务引用提供程序失败。(HRESULT : 0x80131500) the project format is incorrect

c# - 在 Entity Framework Code First 中建模本地化数据

wpf - 在 Windows 8.1 上使用 WindowChrome 时任务栏图标消失

wpf - 多线程 wpf 窗口中的 Printdialog 抛出 TargetInvocationException

c# - WPF 用户控件可编辑属性

c# - License.licx 文件和许可/未许可机器

c# - 从SQL Server数据库表中检索最后一个ID

wpf - DragDrop - DragEnter/DragLeave 事件持续触发

user-controls - WP7 在 UserControl 中使用 LoopingSelector

c# - 重用昂贵的用户控件