Freigeben über


What's a name scope?

In almost all programming languages, names are not globally unique, they are unique only relative to other names in the same name scope. In C++ and C#, a name scope is roughly what goes between curly braces -- { }. And in C++ and C#, namescopes nest -- if the compiler can't find the name in the nearest namescope { }, it will look in the containing namescope.

Xaml names have many of the same issues. In <Button Name="foo">, foo is not unique to the whole program, there could be other xaml files with the same name. And you can instantiate that xaml file multiple times (e.g., multiple windows). And through the use of templates, you can even get the same element multiple times in the same file:

<Window>
<Window.Resources>
<ControlTemplate x:Key="template" TargetType="{x:Type Button}">
<Rectangle Name="foo"/>
</ControlTemplate
</Window.Resources>

<Button Template="{StaticResource template}"/>
<Button Template="{StaticResource template}"/>

</Window>

Once those templates are instantiated, there's two rectangles named "foo"!

WPF handles this with the interface INameScope, which has methods FindName, RegisterName, and UnregisterName. In WPF, namescopes are always associated with a single element, although there's nothing in the namescope design that requires that. The root element in each xaml file gets its own name scope. Instantiated templates each have their own name scope (in the example above, it contains exactly one name -- "foo"). Styles also get their own name scope, mostly so we can name the parts of storyboards. And ResourceDictionary has its own degenerate name scope, a "throw scope", which throws an exception if you try to add a name to it, to help avoid confusion between x:Name and x:Key.

FrameworkElement also has FindName, RegisterName and UnregisterName methods. If the element owns a name scope, the element methods simply call into the name scope's methods. Otherwise, WPF walks up the (logical) tree looking for the nearest namescope. I was a little hesitant to make it so easy to register with a distance scope -- if you're not sure what name scope your registering with, you can't really be sure your name is unique -- but, you need a name to use the storyboard APIs, and in most programs it's fairly easy to be "unique enough" with your names, so we went with it.

I alluded to the similarity between xaml and C# namescopes -- one important difference is that in xaml, namescopes don't nest -- if WPF doesn't find the name you're looking for in the first name scope, it doesn't go out to a bigger name scope. But that's a post for another day...

Comments

  • Anonymous
    June 06, 2006
    There are few details which are still obscure to me:

    1. If I have a control in a Page (page is the root element), and I call control.FindName()... What you say is that the name passed in the FindName() method will be resolved into the Page root element namespace and will not "recurse" into the control's template name-scope?

    2. Then, if #1 is true. How can I obtain an element of the control's template (let's say something like the "PART_blah" method used some places in the Presentation Framework)? I know of the GetTemplateChild() method, but it is marked as "do not use" in the documentation.

    Thanks,

    Marc

  • Anonymous
    June 06, 2006
    To find a named object inside a template:

    button.Template.FindName("name", button)

  • Anonymous
    August 02, 2006
    Is there an easy way to retrieve the current namescope in a MarkupExtension?
    I've tried the IServiceProvider being passed, but it doesn't work.

  • Anonymous
    May 17, 2007
    When you start naming things, you quickly realize that you need a method to disambiguate or resolve conflicts

  • Anonymous
    September 26, 2008
    PingBack from http://cplotts.wordpress.com/2008/09/26/dr-wpf-namescopes/