Области видимости имен XAML в WPFWPF XAML Namescopes

Области имен XAML — это понятие, которое идентифицирует объекты, определенные в XAML.XAML namescopes are a concept that identifies objects that are defined in XAML. Имена из области имен XAML можно использовать для установления связей между именами объектов, определенными в XAML, и эквивалентными им экземплярами из дерева объектов.The names in a XAML namescope can be used to establish relationships between the XAML-defined names of objects and their instance equivalents in an object tree. Области имен XAML в управляемом коде WPFWPF, как правило, создаются при загрузке отдельных корневых страниц XAML для приложения XAML.Typically, XAML namescopes in WPFWPF managed code are created when loading the individual XAML page roots for a XAML application. Области имен XAML, так как программный объект определяются INameScope интерфейсом и также реализуются практическим классом NameScope.XAML namescopes as the programming object are defined by the INameScope interface and are also implemented by the practical class NameScope.

Области имен в загруженных приложениях XAMLNamescopes in Loaded XAML Applications

В более широком контексте программирования или информатики в концепции программирования включается принцип уникального идентификатора или имени, которое можно использовать для доступа к объекту.In a broader programming or computer science context, programming concepts often include the principle of a unique identifier or name that can be used to access an object. В системах, где используются идентификаторы или имена, область имен определяет границы, в пределах которых процесс или технология ищет объект с запрошенным именем, или границы, в пределах которых применяются уникальные имена.For systems that use identifiers or names, the namescope defines the boundaries within which a process or technique will search if an object of that name is requested, or the boundaries wherein uniqueness of identifying names is enforced. Эти общие принципы действительны и для областей имен XAML.These general principles are true for XAML namescopes. В WPF области имен XAML создаются в корневом элементе страницы XAML при загрузке страницы.In WPF, XAML namescopes are created on the root element for a XAML page when the page is loaded. Каждое имя, указанное внутри страницы XAML, начиная с корневой страницы, добавляется в соответствующую область имен XAML.Each name specified within the XAML page starting at the page root is added to a pertinent XAML namescope.

В WPF XAML элементы, являющиеся общими корневыми элементами (например Page, и Window), всегда управляют областью имен XAML.In WPF XAML, elements that are common root elements (such as Page, and Window) always control a XAML namescope. FrameworkElement Если элемент XAMLXAML FrameworkContentElement ,напримерPage или, является корневым элементом страницы в разметке, обработчик неявно добавляет корень,чтобыможнобылопредоставитьрабочуюобластьвидимостиXAML.PageIf an element such as FrameworkElement or FrameworkContentElement is the root element of the page in markup, a XAMLXAML processor adds a Page root implicitly so that the Page can provide a working XAML namescope.

Примечание

Область имен XAML создается для рабочего приложения XAML при выполнении действий сборки WPF, даже если атрибуты Name и x:Name не определены в элементах разметки XAMLXAML.WPF build actions create a XAML namescope for a XAML production even if no Name or x:Name attributes are defined on any elements in the XAMLXAML markup.

При попытке использования одного и того же имени дважды в любой области имен XAML будет вызвано исключение.If you try to use the same name twice in any XAML namescope, an exception is raised. Для кода XAML системы WPF, который содержит код программной части и является компонентом скомпилированного приложения, во время первоначальной компиляции разметки при создании сформированного класса для страницы вызывается исключение при выполнении действий сборки WPF.For WPF XAML that has code-behind and is part of a compiled application, the exception is raised at build time by WPF build actions, when creating the generated class for the page during the initial markup compile. Для кода XAML, разметка которого не скомпилирована действием сборки, исключения, связанные с проблемами области имен XAML, могут вызываться при загрузке кода XAML.For XAML that is not markup-compiled by any build action, exceptions related to XAML namescope issues might be raised when the XAML is loaded. Разработчики XAML должны также учитывать возможность возникновения проблем с областью имен XAML во время разработки.XAML designers might also anticipate XAML namescope issues at design time.

Добавление объектов в деревья объектов среды выполненияAdding Objects to Runtime Object Trees

Область имен XAML системы WPF создается и определяется в момент синтаксического анализа кода XAML.The moment that XAML is parsed represents the moment in time that a WPF XAML namescope is created and defined. Если объект добавляется в дерево объектов уже после того, как выполнен синтаксический анализ кода XAML, сформировавшего это дерево, значение Name или x:Name нового объекта не приводит к автоматическому обновлению сведений из области имен XAML.If you add an object to an object tree at a point in time after the XAML that produced that tree was parsed, a Name or x:Name value on the new object does not automatically update the information in a XAML namescope. Чтобы добавить имя объекта в область имен XAML WPF после загрузки XAML, необходимо вызвать соответствующую реализацию RegisterName для объекта, определяющего область имен XAML, которая обычно является корнем страницы XAML.To add a name for an object into a WPF XAML namescope after XAML is loaded, you must call the appropriate implementation of RegisterName on the object that defines the XAML namescope, which is typically the XAML page root. Если имя не зарегистрировано, на добавленный объект нельзя ссылаться по имени с помощью методов, таких FindNameкак, и его нельзя использовать для нацеленности на анимацию.If the name is not registered, the added object cannot be referenced by name through methods such as FindName, and you cannot use that name for animation targeting.

Наиболее распространенным сценарием для разработчиков приложений является то, что RegisterName вы будете использовать для регистрации имен в области имен XAML в текущем корне страницы.The most common scenario for application developers is that you will use RegisterName to register names into the XAML namescope on the current root of the page. RegisterNameявляется частью важного сценария для раскадровок, предназначенных для объектов анимации.RegisterName is part of an important scenario for storyboards that target objects for animations. Дополнительные сведения см. в разделе Общие сведения о Storyboard.For more information, see Storyboards Overview.

При вызове RegisterName для объекта, отличного от объекта, определяющего область имен XAML, имя по-прежнему регистрируется в области имен XAML, в которой содержится вызывающий объект, как если бы RegisterName вызывался объект, определяющий область имен XAML.If you call RegisterName on an object other than the object that defines the XAML namescope, the name is still registered to the XAML namescope that the calling object is held within, as if you had called RegisterName on the XAML namescope defining object.

Области имен XAML в кодеXAML Namescopes in Code

Вы можете создавать и использовать области имен XAML в коде.You can create and then use XAML namescopes in code. Интерфейсы API и понятия, которые применяются при создании областей имен XAML, совпадают с применяемыми в чистом коде, так как обработчик XAML для WPFWPF использует эти API и понятия при обработке самого кода XAML.The APIs and the concepts involved in XAML namescope creation are the same even for a pure code usage, because the XAML processor for WPFWPF uses these APIs and concepts when it processes XAML itself. Они существуют в основном для поиска объектов по имени в дереве объектов, которое, как правило, частично или полностью задано в XAML.The concepts and API exist mainly for the purpose of being able to find objects by name within an object tree that is typically defined partially or entirely in XAML.

Для приложений, которые создаются программно, а не из загруженного XAML, объект, определяющий область имен XAML INameScope, должен реализовывать или FrameworkElement быть FrameworkContentElement производным классом для поддержки создания области видимости имен XAML на его вхождений.For applications that are created programmatically, and not from loaded XAML, the object that defines a XAML namescope must implement INameScope, or be a FrameworkElement or FrameworkContentElement derived class, in order to support creation of a XAML namescope on its instances.

Также для любого элемента, не загруженного и не обработанного обработчиком XAML, область имен XAML для объекта не создается и не инициализируется по умолчанию.Also, for any element that is not loaded and processed by a XAML processor, the XAML namescope for the object is not created or initialized by default. Необходимо явным образом создать область имен XAML для любого объекта, в котором впоследствии требуется регистрировать имена.You must explicitly create a new XAML namescope for any object that you intend to register names into subsequently. Для создания области имен XAML вызывается статический SetNameScope метод.To create a XAML namescope, you call the static SetNameScope method. Укажите объект, который будет владельцем его в качестве dependencyObject параметра, и новый NameScope вызов конструктора в качестве value параметра.Specify the object that will own it as the dependencyObject parameter, and a new NameScope constructor call as the value parameter.

dependencyObject Если объект, SetNameScope INameScope RegisterName предоставленный как, не является реализацией или FrameworkContentElement, вызов для всех дочерних элементов не будет действовать. FrameworkElementIf the object provided as dependencyObject for SetNameScope is not a INameScope implementation, FrameworkElement or FrameworkContentElement, calling RegisterName on any child elements will have no effect. Если не удается явно создать область видимости имен XAML, вызывает метод, чтобы RegisterName вызвать исключение.If you fail to create the new XAML namescope explicitly, then calls to RegisterName will raise an exception.

Пример использования интерфейсов API для области имен XAML в коде см. в разделе Определение пространства имен.For an example of using XAML namescope APIs in code, see Define a Name Scope.

Области имен XAML в стилях и шаблонахXAML Namescopes in Styles and Templates

Стили и шаблоны WPFWPF позволяют повторно использовать и применять содержимое простым и понятным способом.Styles and templates in WPFWPF provide the ability to reuse and reapply content in a straightforward way. Однако стили и шаблоны могут также включать элементы с именами XAML, определенными на уровне шаблона.However, styles and templates might also include elements with XAML names defined at the template level. Затем один и тот же шаблон может использоваться несколько раз на странице.That same template might be used multiple times in a page. По этой причине стили и шаблоны определяют свои собственные области имен XAML независимо от расположения в дереве объектов, где применяется стиль или шаблон.For this reason, styles and templates both define their own XAML namescopes, independent of whatever location in an object tree where the style or template is applied.

Рассмотрим следующий пример.Consider the following example:

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <Page.Resources>
    <ControlTemplate x:Key="MyButtonTemplate" TargetType="{x:Type Button}">
      <Border BorderBrush="Red" Name="TheBorder" BorderThickness="2">
        <ContentPresenter/>
      </Border>      
    </ControlTemplate>
  </Page.Resources>
  <StackPanel>
    <Button Template="{StaticResource MyButtonTemplate}">My first button</Button>
    <Button Template="{StaticResource MyButtonTemplate}">My second button</Button>
  </StackPanel>
</Page>

Здесь один тот же шаблон применяется к двум разным кнопкам.Here, the same template is applied to two different buttons. Если у шаблонов не было дискретных областей имен XAML, имя TheBorder, используемое в шаблоне, вызовет конфликт имен в области имен XAML.If templates did not have discrete XAML namescopes, the TheBorder name used in the template would cause a name collision in the XAML namescope. Каждый экземпляр шаблона имеет свою собственную область имен XAML, поэтому в данном примере каждая область имен XAML экземпляра шаблона будет содержать ровно одно имя.Each instantiation of the template has its own XAML namescope, so in this example each instantiated template's XAML namescope would contain exactly one name.

Стили также определяют собственные области имен XAML, в основном поэтому части раскадровок могут иметь присвоенные индивидуальные имена.Styles also define their own XAML namescope, mostly so that parts of storyboards can have particular names assigned. Эти имена включают конкретные расширения функциональности элемента управления, которые предназначены для элементов с таким именем, даже если шаблон был переопределен при настройке элемента управления.These names enable control specific behaviors that will target elements of that name, even if the template was re-defined as part of control customization.

Из-за независимых областей имен XAML поиск именованных элементов в шаблоне является более затратной задачей, чем поиск нешаблонного именованного элемента на странице.Because of the separate XAML namescopes, finding named elements in a template is more challenging than finding a non-templated named element in a page. Сначала необходимо определить примененный шаблон, получая Template значение свойства элемента управления, в котором применяется шаблон.You first need to determine the applied template, by getting the Template property value of the control where the template is applied. Затем вызывается версия FindNameшаблона, передавая элемент управления, в котором шаблон был применен в качестве второго параметра.Then, you call the template version of FindName, passing the control where the template was applied as the second parameter.

Если вы являетесь автором элемента управления и создаете соглашение, в котором определенный именованный элемент в примененном шаблоне является целью для поведения, определяемого самим элементом управления, можно использовать GetTemplateChild метод из кода реализации элемента управления.If you are a control author and you are generating a convention where a particular named element in an applied template is the target for a behavior that is defined by the control itself, you can use the GetTemplateChild method from your control implementation code. GetTemplateChild Метод защищен, поэтому доступ к нему имеют только автор элемента управления.The GetTemplateChild method is protected, so only the control author has access to it.

Если вы работаете в шаблоне и хотите перейти к области имен XAML, где применяется шаблон, получите значение TemplatedParent, а затем вызовите FindName его.If you are working from within a template, and need to get to the XAML namescope where the template is applied, get the value of TemplatedParent, and then call FindName there. В качестве примера работы в шаблоне можно привести ситуацию, когда пишется реализация обработчика событий, в котором событие будет вызвано из элемента в примененном шаблоне.An example of working within the template would be if you are writing the event handler implementation where the event will be raised from an element in an applied template.

FrameworkElementFindNameметоды и.RegisterName UnregisterNameFrameworkElement has FindName, RegisterName and UnregisterName methods. Если объект, для которого вызываются эти методы, имеет собственную область имен XAML, то методы вызывают методы соответствующей области имен XAML.If the object you call these methods on owns a XAML namescope, the methods call into the methods of the relevant XAML namescope. В противном случае выполняется проверка того, владеет ли родительский элемент областью имен XAML и этот процесс продолжается рекурсивно до тех пор, пока область имен XAML не будет найдена (из-за того что поведение обработчика XAML гарантирует наличие области имен XAML в корне).Otherwise, the parent element is checked to see if it owns a XAML namescope, and this process continues recursively until a XAML namescope is found (because of the XAML processor behavior, there is guaranteed to be a XAML namescope at the root). FrameworkContentElementимеет аналогичные поведения, за исключением того, FrameworkContentElement что ни один из них не владеет областью имен XAML.FrameworkContentElement has analogous behaviors, with the exception that no FrameworkContentElement will ever own a XAML namescope. Методы существуют в FrameworkContentElement , так что вызовы могут пересылаться в конечном итоге FrameworkElement в родительский элемент.The methods exist on FrameworkContentElement so that the calls can be forwarded eventually to a FrameworkElement parent element.

SetNameScopeиспользуется для соответствия новой области имен XAML существующему объекту.SetNameScope is used to map a new XAML namescope to an existing object. Можно вызвать SetNameScope несколько раз, чтобы сбросить или очистить область имен XAML, но это не является распространенным использованием.You can call SetNameScope more than once in order to reset or clear the XAML namescope, but that is not a common usage. Кроме того GetNameScope , обычно не используется из кода.Also, GetNameScope is not typically used from code.

Реализации области имен XAMLXAML Namescope Implementations

Следующие классы реализуют INameScope напрямую:The following classes implement INameScope directly:

ResourceDictionaryне использует имена или области видимости имен XAML; Вместо этого используются ключи, так как это реализация словаря.ResourceDictionary does not use XAML names or namescopes ; it uses keys instead, because it is a dictionary implementation. Единственная причина, с ResourceDictionary которой INameScope реализуется, заключается в том, что она может вызывать исключения в пользовательском коде, которые помогают объяснить различие между истинной областью видимости имен ResourceDictionary XAML и тем, как обработчики ключей, а также убедиться, что области имен XAML не применяются к элементу ResourceDictionary по родительским элементам.The only reason that ResourceDictionary implements INameScope is so it can raise exceptions to user code that help clarify the distinction between a true XAML namescope and how a ResourceDictionary handles keys, and also to assure that XAML namescopes are not applied to a ResourceDictionary by parent elements.

FrameworkTemplateи Style реализуйте INameScope через явные определения интерфейса.FrameworkTemplate and Style implement INameScope through explicit interface definitions. Явные реализации позволяют этим областям видимости имен XAML вести себя по соглашению, когда доступ к ним осуществляется INameScope через интерфейс, что заключается в том, как области имен XAML WPFWPF взаимодействуют внутренними процессами.The explicit implementations allow these XAML namescopes to behave conventionally when they are accessed through the INameScope interface, which is how XAML namescopes are communicated by WPFWPF internal processes. Но явные определения интерфейса не являются частью FrameworkTemplate стандартной API-интерфейса и Style, так как INameScope редко приходится вызывать методы в FrameworkTemplate и Style напрямую, а вместо этого использовать другой API. GetTemplateChildнапример.But the explicit interface definitions are not part of the conventional API surface of FrameworkTemplate and Style, because you seldom need to call the INameScope methods on FrameworkTemplate and Style directly, and instead would use other API such as GetTemplateChild.

Следующие классы определяют собственную область имен XAML с помощью System.Windows.NameScope вспомогательного класса и подключаются к своей реализации области видимости имен XAML с NameScope.NameScope помощью присоединенного свойства:The following classes define their own XAML namescope, by using the System.Windows.NameScope helper class and connecting to its XAML namescope implementation through the NameScope.NameScope attached property:

См. такжеSee also