Язык программирования C#9 и платформа .NET5
public partial class App : Application{private void App_OnStartup(object sender, StartupEventArgs e){}private void App_OnExit(object sender, ExitEventArgs e){}}Обратите внимание, что класс помечен как частичный (
). На самом деле все оконные классы в отделенном коде для файлов XAML помечаются как частичные. В этом-то и кроется решение вопроса, где находится методpartial. Но сначала необходимо выяснить, что происходит при обработке файлов XAML утилитойMain().msbuild.ехеОтображение разметки XAML окна на код C#
Когда утилита
обрабатывает файлmsbuild.exe, она создает для каждого файла XAML в проекте три файла:*.csproj(где*.g.csозначает autogenerated (автоматически сгенерированный)),g(где*.g.i.csозначает /ntelliSense) иi(для BAML (Binary Application Markup Language — двоичный язык разметки приложений)). Такие файлы сохраняются в каталоге*.baml(и могут просматриваться в окне Solution Explorer за счет щелчка на кнопке Show All Files (Показать все файлы )).\obj\DebugЧтобы их увидеть, может потребоваться щелкнуть на кнопке Refresh (Обновить) в окне Solution Explorer, т.к. они не являются частью фактического проекта, а представляют собой артефакты построения.
Чтобы сделать процесс более осмысленным, элементам управления полезно назначить имена. Назначьте имена элементам управления
иButton, как показано ниже:Calendar<Button Name="ClickMe" Content="Button" HorizontalAlignment="Left"Margin="10,10,0,0"VerticalAlignment="Top" Width="75" Click="Button_Click">// Для краткости разметка не показана,</Button><Calendar Name="MyCalendar" HorizontalAlignment="Left" Margin="10,41,0,0"VerticalAlignment="Top"/>Теперь повторно скомпилируйте решение (или проект) и обновите файлы в окне Solution Explorer. Если открыть файл
в текстовом редакторе, то внутри обнаружится класс по имениMainWindow.g.cs, который расширяет базовый классMainWindow. Имя данного класса является прямым результатом действия атрибутаWindowв начальном дескрипторех:Class.<Window>В классе
определена закрытая переменная-член типаMainWindow(с именемbool), которая не была напрямую представлена в разметке XAML. Указанный член данных используется для того, чтобы определить (и гарантировать) присваивание содержимого окна только один раз. Класс также содержит переменную-член типа_contentLoadedпо имениSystem.Windows.Controls.Button. Имя элемента управления основано на значении атрибутаClickMeв открывающем объявленииx:Name. В классе не будет присутствовать переменная для элемента управления<Button>. Причина в том, что утилитаCalendarсоздает переменную для каждого именованного элемента управления в разметке XAML, который имеет связанный код в отделенном коде. Когда такого кода нет, потребность в переменной отпадает. Чтобы еще больше запутать ситуацию, если бы элементу управленияmsbuild.ехене назначалось имя, то и для него не было бы предусмотрено переменной. Это часть магии WPF, которая связана с реализацией интерфейсаButton.IComponentConnectorСгенерированный компилятором класс также явно реализует интерфейс
из WPF, определенный в пространстве именIComponentConnector. В интерфейсеSystem.Windows.Markupимеется единственный методIComponentConnector, который реализован для подготовки каждого элемента управления, определенного в разметке, и обеспечения логики событий, как указано в исходном файлеConnect(). Можно заметить обработчик, настроенный для события щелчка на кнопкеMainWindow.xaml. Перед завершением метода переменная-членClickMeустанавливается в_contentLoaded. Вот как выглядит данный метод:truevoid System.Windows.Markup.IComponentConnector.Connect(int connectionId,object target){switch (connectionId){case 1:this.ClickMe = ((System.Windows.Controls.Button)(target));#line 11 "..\..\MainWindow.xaml"this.ClickMe.Click +=new System.Windows.RoutedEventHandler(this.Button_Click);#line default#line hiddenreturn;}this._contentLoaded = true;}Чтобы продемонстрировать влияние неименованных элементов управления на код, добавьте к календарю обработчик события
. Перекомпилируйте приложение, обновите файлы и заново загрузите файлSelectedDatesChanged. Теперь в методеMainWindow.g.csприсутствует следующий блок кода:Connect()