问题描述
所以在下面的示例代码中,我创建了一个 UserControl UserControldChild,它是主窗口 Window1.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!
}
}
}
下面的用户控件:
//(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 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.
这在 Namerelated APIs 部分中记录(有些差)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 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!