Why doesnt Window.FindName() discover the x:Name of a button in a child UserControl? AKA how do NameScopes work?

*爱你&永不变心* 提交于 2019-12-19 08:06:44

问题


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?

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 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.


回答1:


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

This is (somewhat poorly) documented in the Name related APIs section of the XAML Namescopes page.

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.

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.

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.

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.



来源:https://stackoverflow.com/questions/1764364/why-doesnt-window-findname-discover-the-xname-of-a-button-in-a-child-usercont

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!