Книги онлайн и без регистрации » Разная литература » Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 311 312 313 314 315 316 317 318 319 ... 407
Перейти на страницу:
найти настройки, касающиеся отладки XAML, на вкладке ToolsOptionsDebuggingHot Reload (Сервис►Параметры►Отладкам►Горячая перезагрузка). Снятие отметки с верхнего флажка предотвращает перекрытие окон приложения окном отладчика (рис. 24.11).

Исследование файла Арр.xaml

Как проект узнает, какое окно отображать? Еще большая интрига в том, что в результате исследования файлов кода, относящихся к приложению, метод Main() обнаружить не удастся. Вы уже знаете, что приложения обязаны иметь точку входа, так как же .NET Core становится известно, каким образом запускать приложение? К счастью, оба связующих элемента автоматически поддерживаются через шаблоны Visual Studio и инфраструктуру WPF.

Чтобы разгадать загадку, какое окно открывать, в файле Арр.xaml посредством разметки определен класс приложения. В дополнение к определениям пространств имен он определяет свойства приложения, такие как StartupUri, ресурсы уровня приложения (рассматриваемые в главе 27) и специфические обработчики для событий приложения вроде Startup и Exit. В StartupUri указано окно, подлежащее загрузке при запуске. Откройте файл Арр.xaml и проанализируйте разметку в нем:

<Application x:Class="WpfTesterApp.App"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:WpfTesterApp"

  StartupUri="MainWindow.xaml">

  <Application.Resources>

  </Application.Resources>

</Application>

С применением визуального конструктора XAML и средства завершения кода Visual Studio добавьте обработчики для событий Startup и Exit. Обновленная разметка XAML должна выглядеть примерно так (изменение выделено полужирным):

<Application x:Class="WpfTesterApp.App"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:WpfTesterApp"

  StartupUri="MainWindow.xaml" Startup="App_OnStartup" Exit="App_OnExit">

  <Application.Resources>

  </Application.Resources>

</Application>

Содержимое файла Арр.xaml.cs должно быть похожим на приведенное ниже:

public partial class App : Application

{

  private void App_OnStartup(object sender, StartupEventArgs e)

  {

  }

  private void App_OnExit(object sender, ExitEventArgs e)

  {

  }

}

Обратите внимание, что класс помечен как частичный (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 — двоичный язык разметки приложений)). Такие файлы сохраняются в каталоге objDebug (и могут просматриваться в окне Solution Explorer за счет щелчка на кнопке Show All Files (Показать все файлы )).

Чтобы их увидеть, может потребоваться щелкнуть на кнопке 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 (с именем _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. Можно заметить обработчик, настроенный для события щелчка на кнопке ClickMe. Перед завершением метода переменная-член _contentLoaded устанавливается в true. Вот как выглядит данный метод:

void 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 hidden

    return;

  }

  this._contentLoaded = true;

}

Чтобы продемонстрировать влияние неименованных элементов управления на код, добавьте к календарю обработчик события SelectedDatesChanged. Перекомпилируйте приложение, обновите файлы и заново загрузите файл MainWindow.g.cs. Теперь в методе Connect() присутствует следующий блок кода:

#line 20 "....MainWindow.xaml"

this.MyCalendar.SelectedDatesChanged += new

     System.EventHandler<System.Windows.Controls.SelectionChangedEventArgs>(

         this.MyCalendar_OnSelectedDatesChanged);

Он сообщает инфраструктуре о том, что элементу управления в строке 20 файла XAML назначен обработчик события SelectedDatesChanged, как показано в предыдущем коде.

Наконец, класс MainWindow определяет и реализует метод по имени InitializeComponent(). Вы могли бы ожидать, что данный метод содержит код, который настраивает внешний вид и поведение каждого элемента управления, устанавливая его разнообразные свойства (Height, Width, Content и т.д.). Однако это совсем не так! Как тогда элементы управления получают корректный пользовательский интерфейс? Логика в методе InitializeComponent() выясняет местоположение встроенного в сборку ресурса, который именован идентично исходному файлу *.xaml:

public void InitializeComponent() {

  if (_contentLoaded) {

    return;

    }

    _contentLoaded = true;

  System.Uri resourceLocater =

  

1 ... 311 312 313 314 315 316 317 318 319 ... 407
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. В коментария нецензурная лексика и оскорбления ЗАПРЕЩЕНЫ! Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?