Обратите внимание, что класс помечен как частичный (
partial
). На самом деле все оконные классы в отделенном коде для файлов XAML помечаются как частичные. В этом-то и кроется решение вопроса, где находится метод
Main
. Но сначала необходимо выяснить, что происходит при обработке файлов XAML утилитой
msbuild.ехе
.
Отображение
разметки XAML окна на код C#
Когда утилита
msbuild.exe
обрабатывает файл
*.csproj
, она создает для каждого файла XAML в проекте три файла:
*.g.cs
(где
g
означает autogenerated (автоматически сгенерированный)),
*.g.i.cs
(где
i
означает /ntelliSense) и
*.baml
(для BAML (Binary Application Markup Language — двоичный язык разметки приложений)). Такие файлы сохраняются в каталоге
\obj\Debug
(и могут просматриваться в окне Solution Explorer за счет щелчка на кнопке Show All Files (Показать все файлы )).
Чтобы их увидеть, может потребоваться щелкнуть на кнопке Refresh (Обновить) в окне Solution Explorer, т.к. они не являются частью фактического проекта, а представляют собой артефакты построения.
Чтобы сделать процесс более осмысленным, элементам управления полезно назначить имена. Назначьте имена элементам управления
Теперь повторно скомпилируйте решение (или проект) и обновите файлы в окне Solution Explorer. Если открыть файл
MainWindow.g.cs
в текстовом редакторе, то внутри обнаружится класс по имени
MainWindow
, который расширяет базовый класс
Window
. Имя данного класса является прямым результатом действия атрибута
х:Class
в начальном дескрипторе
<Window>
.
В классе
MainWindow
определена закрытая переменная-член типа
bool
(с именем
_contentLoaded
), которая не была напрямую представлена в разметке XAML. Указанный член данных используется для того, чтобы определить (и гарантировать) присваивание содержимого окна только один раз. Класс также содержит переменную-член типа
System.Windows.Controls.Button
по имени
ClickMe
. Имя элемента управления основано на значении атрибута
x:Name
в открывающем объявлении
<Button>
. В классе не будет присутствовать переменная для элемента управления
Calendar
. Причина в том, что утилита
msbuild.ехе
создает переменную для каждого именованного элемента управления в разметке XAML, который имеет связанный код в отделенном коде. Когда такого кода нет, потребность в переменной отпадает. Чтобы еще больше запутать ситуацию, если бы элементу управления
Button
не назначалось имя, то и для него не было бы предусмотрено переменной. Это часть магии WPF, которая связана с реализацией интерфейса
IComponentConnector
.
Сгенерированный компилятором класс также явно реализует интерфейс
IComponentConnector
из WPF, определенный в пространстве имен
System.Windows.Markup
. В интерфейсе
IComponentConnector
имеется единственный метод
Connect
, который реализован для подготовки каждого элемента управления, определенного
в разметке, и обеспечения логики событий, как указано в исходном файле
MainWindow.xaml
. Можно заметить обработчик, настроенный для события щелчка на кнопке
Он сообщает инфраструктуре о том, что элементу управления в строке 20 файла XAML назначен обработчик события
SelectedDatesChanged
, как показано в предыдущем коде.
Наконец, класс
MainWindow
определяет и реализует метод по имени
InitializeComponent
. Вы могли бы ожидать, что данный метод содержит код, который настраивает внешний вид и поведение каждого элемента управления, устанавливая его разнообразные свойства (
Height
,
Width
,
Content
и т.д.). Однако это совсем не так! Как тогда элементы управления получают корректный пользовательский интерфейс? Логика в методе
InitializeComponent
выясняет местоположение встроенного в сборку ресурса, который именован идентично исходному файлу
*.xaml
:
public void InitializeComponent {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Uri resourceLocater =
new System.Uri("/WpfTesterApp;component/mainwindow.xaml",
Здесь возникает вопрос: что собой представляет этот встроенный ресурс?
Роль BAML
Как и можно было предположить, формат BAML является компактным двоичным представлением исходных данных XAML. Файл
*.baml
встраивается в виде ресурса (через сгенерированный файл
*.g.resources
) в скомпилированную сборку. Ресурс BAML содержит все данные, необходимые для настройки внешнего вида и поведения виджетов пользовательского интерфейса (т.е. свойств вроде