为什么Window.FindName()无法在子UserControl中发现按钮的x:Name?AKA NameScopes如何工作? [英] Why doesnt Window.FindName() discover the x:Name of a button in a child UserControl? AKA how do NameScopes work?

查看:70
本文介绍了为什么Window.FindName()无法在子UserControl中发现按钮的x:Name?AKA NameScopes如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在下面的示例代码中,我创建了一个UserControl UserControldChild,它是主WindowWindow1.xaml的子级.为什么 FindName()方法在下面的代码中找不到"myButton"?

So in the example code below, I create a UserControl UserControldChild which is a child of the main Window, Window1.xaml. Why does the FindName() method fail to find the "myButton" in the code below?

这必须与 WPF XAML NameScopes 有关,但是我还没有找到关于NameScope工作原理的很好的解释.有人可以启发我吗?

This must have to do with the WPF XAML NameScopes, but I have yet to find a good explanation as to how NameScope works. Can someone enlighten me?

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

下面的UserControl:

UserControl below:

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

如果未正确回答,我找到了一种替代方法,它使用了

In case this doesn't get answered properly, I found an alternative to using FindName() documented in the post here.

推荐答案

您是正确的-这与XAML名称范围有关.

You are correct - this has to do with XAML Namescopes.

(有点差)在与名称相关的API部分中进行了说明XAML名称范围页面.

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

Basically, if you have a FrameworkElement or FrameworkContentElement, it will define its own name scope. If you call FindName() on a type that doesn't have a namescope, WPF searches up thet ree until it finds an element that does define a namescope, then searches within that namescope.

在您的情况下,它是在Window的名称范围(它是一个FrameworkContentElement,因此它定义了自己的作用域)上进行搜索.它只是搜索在该范围内定义的元素.

In your case, it's searching at Window's namescope (it's a FrameworkContentElement, so it defines its own scope). It just searches elements defined in that scope.

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

In your case, the button is in the UserControl's namescope, though, so Window.FindName() doesn't find it. There is no automatically searching down the tree into lower level scopes.

这是一件好事-您的窗口"不应该或不想要有关其正在使用的UserControl的内部详细信息的任何信息.如果需要在UserControl中使用属性,则应在UserControl级别上公开这些属性-让控件管理自己的子级.

This is a good thing - your "Window" shouldn't know or want to know anything about internal details of a UserControl it's using. If you need properties within the UserControl, they should be exposed at the UserControl level - let the control manage its own children.

这篇关于为什么Window.FindName()无法在子UserControl中发现按钮的x:Name?AKA NameScopes如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆