Перейти к содержимому

Initializecomponent c что это

  • автор:

IComponent Connector. Initialize Component Method

Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.

Loads the compiled page of a component.

public: void InitializeComponent();
public void InitializeComponent ();
abstract member InitializeComponent : unit -> unit
Public Sub InitializeComponent ()

Remarks

Implementations of InitializeComponent are widely observable as part of the infrastructure provided by frameworks or technologies that use XAML combined with application and programming models. For example, whenever you look at the generated classes for XAML root elements in WPF pages and applications, you will see InitializeComponent defined in the output. That method also exists in the compiled assembly and plays a role in the WPF application model of loading the XAML UI content at XAML parse time. For more information on the WPF integration of the InitializeComponent concept, see Application Management Overview or Code-Behind and XAML in WPF.

Классы отделенного кода XAML

Язык XAML позволяет конструировать пользовательский интерфейс, но для создания функционирующего приложения необходим способ подключения обработчиков событий. XAML позволяет легко это сделать с помощью атрибута Class, показанного ниже:

Префикс пространства имен «x» помещает атрибут Class в пространство имен XAML, что означает более общую часть языка XAML. Фактически атрибут Class сообщает анализатору XAML, чтобы он сгенерировал новый класс с указанным именем. Этот класс наследуется от класса, именованного элементом XML. Другими словами, этот пример создает новый класс по имени MainWindow, который наследуется от базового класса Window.

Класс MainWindow генерируется автоматически во время компиляции. И здесь начинается самое интересное. Вы можете предоставить часть класса MainWindow, которая будет объединена с автоматически сгенерированной частью этого класса. Указанная вами часть — блестящий контейнер для кода обработки событий.

Эта «магия» возможна благодаря средству C#, известному под названием частичные классы (partial class). Частичные классы позволяют разделить класс на две или более отдельных части во время разработки, которые соединяются вместе в скомпилированной сборке. Частичные классы могут применяться во многих сценариях управления кодом, но более всего удобны, когда код должен объединяться с файлом, сгенерированным визуальным конструктором.

Среда Visual Studio оказывает помощь, автоматически создавая частичный класс, куда можно поместить код обработки событий. Например, при создании приложения по имени WpfApplication1, содержащего окно по имени MainWindow. Visual Studio начнет с создания следующего базового каркаса класса:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApplication1 < /// /// Логика взаимодействия для MainWindow.xaml /// public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >> > 

Во время компиляции приложения код XAML, определяющий пользовательский интерфейс (такой как MainWindow.xaml), транслируется в объявление типа CLR, объединенного с логикой файла класса отделенного кода (подобного MainWindow.xaml.сs), формируя один общий модуль.

Метод InitializeComponent()

В данный момент класс MainWindow не содержит реальной функциональности. Однако он включает одну важную деталь — конструктор по умолчанию, который вызывает метод InitializeComponent(), когда создается экземпляр класса.

Метод InitializeComponent() играет ключевую роль в приложениях WPF. По этой причине никогда не следует удалять вызов InitializeComponent() из конструктора окна. В случае добавления к классу окна другого конструктора обязательно предусмотрите в нем вызов InitializeComponent().

Метод InitializeComponent() не видим в исходном коде, потому что генерируется автоматически при компиляции приложения. По существу все, что делает InitializeComponent() — это вызов метода LoadComponent() класса System.Windows.Application. Метод LoadComponent() извлекает код BAML (скомпилированный XAML) из сборки и использует его для построения пользовательского интерфейса.

При разборе BAML он создает объекты каждого элемента управления, устанавливает их свойства и присоединяет все обработчики событий.

Именование элементов

Есть еще одна деталь, которая должна приниматься во внимание. В классе отделенного кода часто требуется программно манипулировать элементами управления. Например, необходимо читать либо изменять свойства, а также присоединять или отсоединять обработчики событий на лету. Чтобы обеспечить такую возможность, элемент управления должен включать XAML-атрибут Name. В предыдущем примере элемент Grid не содержит атрибут Name, поэтому манипулировать им в отделенном коде не получится.

Ниже показано, как назначить имя элементу Grid:

Можно внести это изменение в документ XAML вручную или выбрать элемент в визуальном конструкторе Visual Studio и установить свойство Name в окне Properties (Свойства).

В обоих случаях атрибут Name сообщит анализатору XAML о необходимости добавить поле следующего вида к автоматически сгенерированной части класса MainWindow:

private System.Windows.Controls.Grid MyGrid;

Теперь с этим элементом можно взаимодействовать в коде класса MainWindow указывая имя MyGrid:

MessageBox.Show("Размер сетки: " + MyGrid.ActualWidth + "x" + MyGrid.ActualHeight);

Такая техника мало что дает простому примеру, но становится намного важнее, когда требуется читать значения из элементов управления вводом, таких как текстовые поля и списки.

Показанное ранее свойство Name является частью языка XAML и используется для того, чтобы помочь в интеграции класса отделенного кода. Из-за того, что многие классы определяют собственное свойство Name, происходит некоторая путаница. (Примером может служить базовый класс FrameworkElement, от которого наследуются все элементы WPF.) Анализаторы XAML элегантно справляются с этой проблемой. Можно либо установить XAML-свойство Name (используя префикс х:), либо свойство Name, относящееся к действительному элементу (опустив префикс).

В любом случае результат один и тот же — указанное имя используется в файле автоматически сгенерированного кода и применяется для установки свойства Name.

Это значит, что следующая разметка эквивалентна тому, что вы уже видели:

Такой трюк работает только в том случае, если включающий свойство Name класс оснащен атрибутом RuntimeNameProperty. Атрибут RuntimeNameProperty указывает на то, какое свойство должно трактоваться в качестве имени экземпляра этого типа. (Очевидно, обычно таким свойством является Name.) Класс FrameworkElement содержит атрибут RuntimeNameProperty, так что никаких проблем нет.

В традиционном приложении Windows Forms каждый элемент управления имеет имя. В приложении WPF такого требования нет. Однако при создании окна перетаскиванием элементов на поверхность визуального конструктора Visual Studio каждому элементу назначается автоматически сгенерированное имя. Таково соглашение. Если вы не собираетесь взаимодействовать с элементом в коде, то можете удалить атрибут Name из кода разметки.

Управление объявлениями классов и переменных-членов

Многие из этих ключевых полей вы увидите в действии там, где они понадобятся. Давайте в качестве простого примера рассмотрим следующее определение XAML , в котором используются ключевые слова ClassModifier и FieldModifier, а также x:Name и x:Class:

По умолчанию все определения сгенерированных типов C#/XAML в WPF являются внутренними (internal), а члены — общедоступными (public). Однако на основе показанного определения XAML результирующий автоматически сгенерированный файл содержит тип класса internal с public-членом Button:

 [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")] internal partial class MainWindow : System.Windows.Window, System.Windows.Markup.IComponentConnector < #line 6 "..\..\..\MainWindow.xaml" [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] internal System.Windows.Controls.Grid MyGrid; #line default #line hidden /// /// Btn1 Name Field /// #line 8 "..\..\..\MainWindow.xaml" [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")] public System.Windows.Controls.Button Btn1;

Приложение и класс Application

В предыдущих главах мы работали непосредственно с окном приложения, которое представлено классом Window, его разметкой, добавляли в нее элементы, создавали для него код на C#. Однако само приложение начинается не с класса Window , а с класса Application . По умолчанию при создании проекта WPF создается файл App.xaml и класс связанного кода App.xaml.cs :

Класс Application в WPF и C#

Файл App.xaml выглядит примерно так:

С помощью атрибута x:Class элемент Application задает полное название производного класса приложения. По умолчанию класс называется App , с указанием названия проекта, то есть в данном случае HelloApp.App

Как правило, основная задача данного файла состоит в определении ресурсов, общих для приложения. Поэтому тут по умолчанию определен пустой элемент Application.Resources , в который, собственно, и помещаются ресурсы.

Также здесь декларативным путем можно прикрепить к событиям приложения обработчики.

С помощью атрибута StartupUri устанавливается путь к разметке xaml, с которого начинается выполнение приложения. По умолчанию это разметка окна MainWindow, определенного в файле MainWindow.xaml . Если у нас в приложении несколько окон, тут мы можем указать то, которое будет запускаться при вызове приложения.

файл App.xaml.cs также содержит определение класса App. По умолчанию этот класс совершенно пустой:

public partial class App : Application

В нем мы можем задать обработчики событий приложения, либо какую-то другую глобальную для всего приложения логику.

Таким образом, у нас получается, что оба файла App.xaml и App.xaml.cs содержат определение одного и того же класса App. Однако в конечном счете они будут компилироваться в один файл приложения App.g.cs , который вы можете найти после компиляции приложения в каталоге проекта obj/Debug/netX.0-windows

Компиляция приложения WPF на C# и App.g.cs

Данный класс будет выглядеть примерно так:

public partial class App : System.Windows.Application < [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")] public void InitializeComponent() < #line 5 "..\..\..\App.xaml" this.StartupUri = new System.Uri("MainWindow.xaml", System.UriKind.Relative); #line default #line hidden >[System.STAThreadAttribute()] [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.3.0")] public static void Main() < HelloApp.App app = new HelloApp.App(); app.InitializeComponent(); app.Run(); >>

Входной точкой в программу (как и в любое другое приложение на C#) является метод Main, в котором создается экземпляр приложения и производится начальная инициализация и вызов главного окна программы.

Так как WPF требует, чтобы главный поток работал в однопоточном подразделении (Single-threaded apartment), то метод Main помечается атрибутом STAThreadAttribute . Однопоточное подразделение содержит один поток, в данном случае главный. Это означает, что к элементам, созданным в этом потоке можно обратиться только из этого же потока. В то же время WPF предлагает эффективный способ взаимодействия между потоками, о котором мы позже поговорим.

С помощью метода InitializeComponent происходит инициализация приложение: установка главного окна для запуска. И далее само приложение запускается через вызов app.Run() .

Также в той же папке можно найти файл App.g.i.cs , который имеет идентичное содержимое, но применяется различными службами Visual Studion, например, Intellisense.

Однако это не жестко заданная организация файлов приложения, и мы ее можем переопределить и установить точку входа в приложение сами. Для этого, во-первых, удалим файл App.g.cs . И во-вторых, изменим код App.xaml.cs :

using System; using System.Windows; using HelloApp; public partial class App : Application < [STAThread] static void Main() < App app = new App(); MainWindow window = new MainWindow(); window.Title = "Hello METANIT.COM"; app.Run(window); >>

Фактически файл App.xaml.cs стал похож на компилируемый файл App.g.cs . Здесь мы сразу определяем метод Main, создаем главное окно — объект класса MainWindows, устанавливаем его заголовок и запускаем ее.

И после запуска нам отобразится главное окно приложения с измененным заголовком.

Initializecomponent c что это

При создании нового проекта WPF в дополнение к создаваемому файлу MainWindow.xaml создается также файл отделенного кода MainWindow.xaml.cs, где, как предполагается, должна находится логика приложения связанная с разметкой из MainWindow.xaml. Файлы XAML позволяют нам определить интерфейс окна, но для создания логики приложения, например, для определения обработчиков событий элементов управления, нам все равно придется воспользоваться кодом C#.

По умолчанию в разметке окна используется атрибут x:Class :

Атрибут x:Class указывает на класс, который будет представлять данное окно и в который будет компилироваться код в XAML при компиляции. То есть во время компиляции будет генерироваться класс XamlApp.MainWindow , унаследованный от класса System.Windows.Window .

Кроме того в файле отделенного кода MainWindow.xaml.cs, который Visual Studio создает автоматически, мы также можем найти класс с тем же именем — в данном случае класс XamlApp.MainWindow. По умолчанию он имеет некоторый код:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace XamlApp < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >> >

По сути пустой класс, но этот класс уже выполняет некоторую работу. Во время компиляции этот класс объединяется с классом, сгенерированном из кода XAML. Чтобы такое слияние классов во время компиляции произошло, класс XamlApp.MainWindow определяется как частичный с модификатором partial . А через метод InitializeComponent() класс MainWindow вызывает скомпилированный ранее код XAML, разбирает его и по нему строит графический интерфейс окна.

Взаимодействие кода C# и XAML

В приложении часто требуется обратиться к какому-нибудь элементу управления. Для этого надо установить у элемента в XAML свойство Name .

Еще одной точкой взаимодействия между xaml и C# являются события. С помощью атрибутов в XAML мы можем задать события, которые будут связанны с обработчиками в коде C#.

Итак, создадим новый проект WPF, который назовем XamlApp. В разметке главного окна определим два элемента: кнопку и текстовое поле.

И изменим файл отделенного кода, добавив в него обработчик нажатия кнопки:

using System.Windows; namespace XamlApp < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); >private void Button_Click(object sender, RoutedEventArgs e) < string text = textBox1.Text; if (text != "") < MessageBox.Show(text); >> > >

Определив имена элементов в XAML, затем мы можем к ним обращаться в коде c#: string text = textBox1.Text .

При определении имен в XAML надо учитывать, что оба пространства имен «http://schemas.microsoft.com/winfx/2006/xaml/presentation» и «http://schemas.microsoft.com/winfx/2006/xaml» определяют атрибут Name , который устанавливает имя элемента. Во втором случае атрибут используется с префиксом x : x:Name . Какое именно пространство имен использовать в данном случае, не столь важно, а следующие определения имени x:Name=»button1″ и Name=»button1″ фактически будут равноценны.

В обработчике нажатия кнопки просто выводится сообщение , введенное в текстовое поле. После определения обработчика мы его можем связать с событием нажатия кнопки в xaml через атрибут Click: Click=»Button_Click» . В результате после нажатия на кнопку мы увидим в окне введенное в текстовое поле сообщение.

XAML в WPF

Создание элементов в коде C#

Еще одну форму взаимодействия C# и XAML представляет создание визуальных элементов в коде C#. Например, изменим код xaml следующим образом:

Здесь для элемента Grid установлено свойство x:Name , через которое мы можем к нему обращаться в коде. И также изменим код C#:

using System.Windows; using System.Windows.Controls; namespace XamlApp < public partial class MainWindow : Window < public MainWindow() < InitializeComponent(); Button myButton = new Button(); myButton.Width = 100; myButton.Height = 30; myButton.Content = "Кнопка"; layoutGrid.Children.Add(myButton); >> >

В конструкторе странцы создается элемент Button и добавляется в Grid. И если мы запустим приложение, то увидим добавленную кнопку:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *