Области имен XAML
Область имен XAML сохраняет связи между определенными XAML именами объектов и их эквивалентами экземпляров. Эта концепция аналогична более широкому значению области имен терминов на других языках программирования и технологиях.
Определение областей имен XAML
Имена в области имен XAML позволяют пользователю ссылаться на объекты, которые изначально объявлены в XAML. Внутренний результат анализа XAML заключается в том, что среда выполнения создает набор объектов, которые сохраняют некоторые или все связи этих объектов в объявлениях XAML. Эти связи поддерживаются в виде определенных свойств объектов созданных объектов или предоставляются служебным методам в API модели программирования.
Наиболее типичным применением имени в области имен XAML является прямая ссылка на экземпляр объекта, который включается компиляцией разметки в качестве действия сборки проекта, в сочетании с созданным методом InitializeComponent в шаблонах разделяемых классов.
Вы также можете использовать метод служебной программы FindName самостоятельно во время выполнения, чтобы вернуть ссылку на объекты, определенные с именем в разметке XAML.
Дополнительные сведения о действиях сборки и XAML
То, что происходит технически, заключается в том, что сам XAML проходит компилятор разметки одновременно, что XAML и частичный класс, определяющий для кода, компилируются вместе. Каждый элемент объекта с атрибутом Name или x:Name, определенным в разметке, создает внутреннее поле с именем, соответствующим имени XAML. Это поле изначально пусто. Затем класс создает метод InitializeComponent , который вызывается только после загрузки всего XAML. В логике InitializeComponent каждое внутреннее поле затем заполняется возвращаемым значением FindName для эквивалентной строки имени. Эту инфраструктуру можно наблюдать самостоятельно, просматривая файлы G (созданные) для каждой страницы XAML в подпапке /obj проекта приложения среда выполнения Windows после компиляции. Кроме того, поля и метод InitializeComponent отображаются как члены результирующей сборки, если вы отражаете их или в противном случае проверяете содержимое языка интерфейса.
Обратите внимание, что специально для расширений компонентов Visual C++ (C++/CX) поле резервного копирования для ссылки x:Name не создается для корневого элемента XAML-файла. Если вам нужно ссылаться на корневой объект из кода C++/CX, используйте другие API или обход дерева. Например, можно вызвать FindName для известного дочернего элемента, а затем вызвать Parent.
Создание объектов во время выполнения с помощью XamlReader.Load
XAML также можно использовать в качестве строковых входных данных для метода XamlReader.Load , который действует аналогично начальной операции синтаксического анализа источника XAML. XamlReader.Load создает новое автономное дерево объектов во время выполнения. Затем отключенное дерево может быть присоединено к некоторой точке в дереве основного объекта. Необходимо явно подключить созданное дерево объектов, добавив его в коллекцию свойств содержимого, например "Дочерние", или задав другое свойство, которое принимает значение объекта (например, загрузка нового объекта ImageBrush для значения свойства Fill).
Последствия области имен XAML XamlReader.Load
Предварительная область имен XAML, определяемая новым деревом объектов, созданным XamlReader.Load , оценивает все определенные имена в предоставленном XAML для уникальности. Если имена в предоставленном XAML не являются внутренними уникальными на этом этапе, XamlReader.Load создает исключение. Дерево отключенных объектов не пытается объединить область имен XAML с основной областью имен XAML приложения, если или когда она подключена к дереву объектов основного приложения. После подключения деревьев приложение имеет единое дерево объектов, но в нем есть дискретные области имен XAML. Деления происходят в точках соединения между объектами, где для некоторых свойств задано значение, возвращаемое из вызова XamlReader.Load .
Сложность наличия дискретных и отключенных областей имен XAML заключается в том, что вызовы метода FindName , а также прямые ссылки на управляемые объекты больше не работают с унифицированным областью имен XAML. Вместо этого конкретный объект , на который вызывается FindName , подразумевает область, с областью, в которой находится область имен XAML, в которой находится вызывающий объект. В случае ссылки на прямой управляемый объект область подразумевается классом, в котором существует код. Как правило, код за взаимодействием во время выполнения "страницы" содержимого приложения существует в частичном классе, который поддерживает корневую "страницу", и поэтому область имен XAML является корневой областью имен XAML.
При вызове FindName для получения именованного объекта в корневом области имен XAML метод не найдет объекты из дискретного области имен XAML, созданной XamlReader.Load. И наоборот, при вызове FindName из объекта, полученного из дискретного области имен XAML, метод не найдет именованные объекты в корневом области имен XAML.
Эта дискретная проблема с областью имен XAML влияет только на поиск объектов по имени в области имен XAML при использовании вызова FindName .
Чтобы получить ссылки на объекты, определенные в другой области имен XAML, можно использовать несколько методов:
- Следуйте всему дереву в дискретных шагах с помощью свойств родительской и /или коллекции, которые, как известно, существуют в структуре дерева объектов (например, коллекция, возвращаемая Panel.Children).
- Если вы вызываете дискретную область имен XAML и хотите, чтобы корневой области имен XAML всегда было легко получить ссылку на главное окно, отображаемое в настоящее время. Вы можете получить визуальный корень (корневой элемент XAML, также известный как источник содержимого) из текущего окна приложения в одной строке кода с вызовом
Window.Current.Content
. Затем вы можете привести к FrameworkElement и вызвать FindName из этой области. - Если вы вызываете из корневого области имен XAML и хотите, чтобы объект в дискретном области имен XAML лучше всего спланировать в коде и сохранить ссылку на объект, возвращенный XamlReader.Load , а затем добавить в дерево основных объектов. Теперь этот объект является допустимым объектом для вызова FindName в дискретной области имен XAML. Этот объект можно сохранить в виде глобальной переменной или передать его с помощью параметров метода.
- Вы можете избежать проблем с именами и областью имен XAML, проверив визуальное дерево. API VisualTreeHelper позволяет просматривать визуальное дерево с точки зрения родительских объектов и дочерних коллекций, основанных исключительно на позиции и индексе.
Области имен XAML в шаблонах
Шаблоны в XAML обеспечивают возможность повторного использования и повторного использования содержимого простым способом, но шаблоны также могут включать элементы с именами, определенными на уровне шаблона. Затем один и тот же шаблон может использоваться несколько раз на странице. По этой причине шаблоны определяют собственные области имен XAML, независимо от содержащей страницы, в которой применяется стиль или шаблон. Рассмотрим следующий пример:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Page.Resources>
<ControlTemplate x:Key="MyTemplate">
....
<TextBlock x:Name="MyTextBlock" />
</ControlTemplate>
</Page.Resources>
<StackPanel>
<SomeControl Template="{StaticResource MyTemplate}" />
<SomeControl Template="{StaticResource MyTemplate}" />
</StackPanel>
</Page>
Здесь один и тот же шаблон применяется к двум разным элементам управления. Если шаблоны не имели дискретных областей имен XAML, имя MyTextBlock, используемое в шаблоне, приведет к столкновению имен. Каждый экземпляр шаблона имеет свою собственную область имен XAML, поэтому в данном примере каждая область имен XAML экземпляра шаблона будет содержать ровно одно имя. Однако корневой область имен XAML не содержит имя из любого шаблона.
Из-за отдельных областей имен XAML поиск именованных элементов в шаблоне из области страницы, в которой применяется шаблон, требуется другой метод. Вместо вызова FindName для какого-то объекта в дереве объектов сначала вы получите объект, имеющий примененный шаблон, а затем вызовите GetTemplateChild. Если вы являетесь автором элемента управления и создаете соглашение, в котором конкретный именованный элемент в примененном шаблоне является целевым объектом для поведения, определенного самим элементом управления, можно использовать метод GetTemplateChild из кода реализации элемента управления. Метод GetTemplateChild защищен, поэтому к нему имеет доступ только автор элемента управления. Кроме того, существуют соглашения, которые авторы управления должны следовать, чтобы именовать части и части шаблона и сообщать об этих элементах в виде значений атрибутов, применяемых к классу элемента управления. Этот метод делает имена важных частей обнаруживаемыми для управления пользователями, которые могут применить другой шаблон, который потребуется заменить именованные части для поддержания функциональности элемента управления.