Host uwp xaml controls in desktop apps (xaml islands)

Введение в компоновку

Последнее обновление: 11.02.2016

Построение графического интерфейса в Universal Windows Platform базируется на концепции компоновки. Компоновка (layout)
представляет процесс позиционирования элементов внутри контейнера. Благодаря компоновке мы можем уйти от жестко закодированных размеров элементов в сторону
«резинового» дизайна и адаптивных интерфейсов, которые проще подстроить под различные разрешения экранов.

В Universal Windows Platform компоновка выполняется с помощью специальных контейнеров. В частности, нам доступны следующие контейнеры компоновки:
Grid, VariableSizedWrapGrid, StackPanel, SplitView, RelativePanel и Canvas.
Контейнеры компоновки позволяют эффективно распределить доступное пространство между элементами, найти для него наиболее предпочтительные размеры.
Также они могут содержать внутри себя другие контейнеры, например, StackPanel в Grid. Поэтому, чтобы добиться нужного нам эффекта в размещении элементов, мы можем помещать однни контейнеры в другие,
комбинировать их. Кроме того, если нам не хватает стандартных контейнеров, мы можем определить свои с нужной нам функциональностью.

Все выше перечисленные контейнеры компоновки наследуются от класса Panel, которое предоставляет ряд базовых свойств и методов. А само дерево наследования можно представить следующим образом:

В частности, отличительной чертой контейнеров компоновки является свойство Children, которое включает все вложенные контейнер элементы.
Например, возьмем стандартный контейнер Grid:

<Grid x:Name="layoutGrid">
    <Button Content="Hello" />
</Grid>

Здесь в грид помещена кнопка. Этот код эквивалентен следующему:

<Grid x:Name="layoutGrid">
    <Grid.Children>
        <Button Content="Hello" />
    </Grid.Children>
</Grid>

Свойство Children представляет коллекцию , которая содержит объекты UIElement. Практически все стандартные элементы в Universal
Windows Platform представляют тип UIElement. И как многие стандартные коллекции, коллекция Children имеет методы для управления содержимым:

  • : добавляет UIElement в контейнер

  • : удаляет UIElement из контейнера

  • : удаляет элемент из контейнера по индексу в коллекции Children

  • : перемещает элемент в коллекции с одного индекса на другой

  • : удаляет все элементы из коллекции

Например, в коде C# мы могли бы изменять содержимое контейнера компоновки:

Button button1 = new Button { Content = "Button 1", VerticalAlignment=VerticalAlignment.Top };
layoutGrid.Children.Add(button1); // добавляем кнопку
layoutGrid.Children.Remove(button1); // удаляем кнопку
layoutGrid.Children.Clear(); // удаляем все элементы

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

Процесс компоновки

Процесс компоновки проходит два этапа: измерение (measure) и расстановка (arrange). На этапе измерения контейнер производит измерение предпочтительного
для дочерних элементов места. Однако не всегда контейнер имеет достаточно места, чтобы расставить все элементы в соответствии с их предпочтительными размерами, поэтому их
размеры приходится усекать. Затем происходит этап непосредственной расстановки дочерних элементов внутри контейнера.

Теперь рассмотрим подробнее отдельные контейнеры компоновки.

НазадВперед

История навигации

Последнее обновление: 13.02.2016

Объект Frame хранит историю навигации, благодаря чему поддерживает возврат на предыдущую страницу с помощью метода Frame.GoBack(),
либо переход на следующую в истории переходов страницу посредством метода Frame.GoForward().

Для практики с историей навигации продолжим работу с проектом из прошлой темы и добавим в него новую страницу по типу Blank Page,
которую назовем Page3 (либо создадим новый проект, в котором будут три страницы MainPage, Page2 и Page3).

Итак, пусть страница MainPage содержит кнопку:

<Button Content="Вперед" Click="Forward_Click" Margin="10" />

В коде обработчика нажатия кнопки пропишем следующий код:

private void Forward_Click(object sender, RoutedEventArgs e)
{
    if (Frame.CanGoForward)
        Frame.GoForward();
    else
        Frame.Navigate(typeof(Page2));
}

Таким образом, если в истории переходов уже есть страница, на которую переходили с MainPage (то есть свойство Frame.CanGoForward равно true),
то сработает переход к этой странице с помощью Frame.GoForward(). Иначе произойдет переход к странице Page2.

На странице Page2 определим две кнопки:

<StackPanel>
    <TextBlock Text="Страница 2" FontSize="36" />
    <Button Content="Вперед"  Click="Forward_Click" Margin="10" />
    <Button Content="Назад"  Click="Back_Click" Margin="10" />
</StackPanel>

И определим в файле Page2.xaml.cs для них обработчики:

private void Back_Click(object sender, RoutedEventArgs e)
{
    if (Frame.CanGoBack)
        Frame.GoBack();
}
 
private void Forward_Click(object sender, RoutedEventArgs e)
{
    if (Frame.CanGoForward)
        Frame.GoForward();
    else
        Frame.Navigate(typeof(Page3));
}

На третьей странице Page3 определим одну кнопку:

<StackPanel>
    <TextBlock Text="Страница 3" FontSize="36" />
    <Button Content="Назад" Click="Back_Click" Margin="10" />
</StackPanel>

И также добавим обработчик для этой кнопки в файл Page3.xaml.cs:

private void Back_Click(object sender, RoutedEventArgs e)
{
    if (Frame.CanGoBack)
        Frame.GoBack();
}

И после этого мы сможем переходить от одной страницы к другой.

При переходе от одной страницы к другой с помощью метода Navigate() в специальный стек в объекте Frame поверх остальных добавляется информация о страницах.
Этот стек мы можем получить с помощью свойства Frame.BackStack. Так, в нашем случае при цепи переходов MainPage->Page2->Page3,
когда мы окажемся на странице Page, в этом стеке будут два объекта MainPage и Page2. Как и любой стек, Frame.BackStack работает по принципу LIFO. Поэтому при вызове
метода Frame.GoBack() система извлекает из стека первую страницу и осуществляет к ней переход.

Мы можем вручную управлять стеком, например, изменим метод кнопки на странице Page3 таким образом, чтобы переход шел к самой первой странице в стеке:

private void Back_Click(object sender, RoutedEventArgs e)
{
    List<PageStackEntry> pageEntries = Frame.BackStack.ToList();
    if (pageEntries.Count > 0)
        Frame.Navigate(pageEntries.SourcePageType);
}

Каждый объект в стеке представляет тип PageStackEntry, из которого мы можем получить данные о странице. То есть в данном случае переход будет идти обратно к MainPage,
а не к Page2. Причем поскольку здесь используется метод Frame.Navigate(), а не Frame.GoBack(), то извлечения из стека информации о последней странице не будет. Наоборот, при
переходе к MainPage в стек будет добавлена информация о странице Page3.

НазадВперед

Объекты Window и Frame. Управление внешним видом приложения

Последнее обновление: 11.02.2016

Объект Window в UWP используется для представления окна приложения. Хотя напрямую мы работаем преимущественно с элементом Page, который представляет страницу приложения, и его кодом,
но фактически объект Window является контейнером для элемента Page.

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

Чтобы получить текущее окно приложения, мы можем использовать статическое свойство Current:

Window window = Window.Current;

Содержимое окна устанавливается с помощью свойства Content. Чтобы окно стало активным для пользователя и чтобы пользователь смог с ним
взаимодействовать, у окна надо вызвать метод Activate().

Немного экспериментируем с объектом Window. Для этого перейдем опять же в файле App.xaml.cs к методу OnLaunched(), который запускается при старте приложения,
и удалим (или закомментируем) все его содержимое:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
}

И если мы запустим приложение, то нам просто отобразится экран заставки, потому что содержимое текущего объекта Window не установлено.
Поэтому изменим метод OnLaunched следующим образом:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
	Window.Current.Content = new Button()
    {
        Content = "Привет мир!",
        HorizontalAlignment = HorizontalAlignment.Center,
        Background = new SolidColorBrush(Windows.UI.Colors.LightPink)
    };
    Window.Current.Activate();
}

В данном случае в качестве содержимого окна устанавливается кнопка

Причем важно сделать оба шага: установка свойства Content и активацию окна посредством
метода. В итоге при запуске мы увидим следующее окно:

Объект Frame

Как правило, для установки содержимого в окне приложения используются не отдельные элементы управления типа кнопок или текстовых поле, а фреймы —
объекты типа Frame. Фреймы упрощают организацию содержимого в приложении, например, в виде отдельных страниц — элементов Page и передачу их
в объект Window.

Для перехода к отдельной странице Frame использует метод Navigate(), в который передается тип страницы. Так, у нас по умолчанию в проекте
есть одна страница MainPage, и изменим метод , чтобы в качестве контента окна загружалась именно эта страница:

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
	Frame frame = new Frame();
    Window.Current.Content = frame;
    frame.Navigate(typeof(MainPage));
    Window.Current.Activate();
}

Управление видом приложения

Платформа Universal Windows Platform предоставляет нам класс Windows.UI.ViewManagement.ApplicationView, который позволяет управлять представлением приложения.
В частности, в нем определены следующие методы и свойства:

  • GetForCurrentView(): статический метод, который возвращает объект ApplicationView, связанный с текущим приложением

  • SetPreferredMinSize(Size minSize): устанавливает минимальные значения для высоты и ширины окна приложения

  • ExitFullScreenMode(): осуществляет выход из полноэкранного режима

  • SetDesiredBoundsMode(): устанавливает предпочтительные границы для окна приложения

  • Title: задает заголовок окна приложения

  • TitleBar: возвращает ссылку на верхнюю панель окна приложения или TitleBar

  • VisibleBounds: возвращает ссылку на границы окна приложения

Используя эти методы и свойства, мы динамически можем управлять внешним видом приложения. Если наша цель — сразу задать приложению некоторые параметры, которые
не должны меняться в течение работы приложения, то лучше это сделать в главном классе приложения App.xaml.cs в методе . Однако при
необходимости мы их можем вызвать в любом месте приложения. Например, из кода главной страницы приложения:

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();

        // получаем ссылку на внешний вид приложения
        Windows.UI.ViewManagement.ApplicationView appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
		// минимальный размер 300х250
        appView.SetPreferredMinSize(new Size(300, 250));
        // установка заголовка
        appView.Title = "Принципиально новое приложение";
        // получаем ссылку на TitleBar
        Windows.UI.ViewManagement.ApplicationViewTitleBar titleBar = appView.TitleBar;
        // установка красного цвета панели
        titleBar.BackgroundColor = Windows.UI.Colors.Red;
    }
}

Окно приложения после запуска:

НазадВперед

Создание проекта. Что нужно заложить с самого начала?

Давайте разберемся:

  • Папка Assets. В данной папке по задумке вы должны хранить ресурсы вашего приложения, такие как, например, картинки. По умолчанию, данная папка содержит обязательные картинки-заплатки, выступающие в роли логотипа, и о них я еще поговорю подробнее в одной из статей данного цикла. К слову, вам не обязательно хранить эти и другие ресурсы в этой папке. Как, собственно, у вас нет ограничений по количеству папок и подпапок с ресурсами.
  • Файл App.xaml и связанный с ним App.xaml.cs/vb выполняют практически ту же функцию, что и Application в WPF. В App.xaml вы можете прописать ресурсы приложения, а также указать предпочтительную тему (светлая или темная) в свойстве RequestedTheme. В файле кода вы можете управлять жизненным циклом приложения. Тема жизненного цикла приложений UWP довольно обширна и подробнее о том, что это такое, можно почитать здесь. Также файл App.xaml.cs/vb можно использовать для размещения глобальных переменных приложения, но это уже зависит от шаблона программирования, который вы решите использовать. Например, для UWP больше походит MVVM, который я использовать не буду, но опытным разработчикам крайне рекомендую.
  • Файл App1_TemporaryKey.pfx является временным сертификатом, подписывающим ваше приложение, и нужным, чтобы оно могло запускаться на устройстве. Больше знать нам о нем ничего не нужно. Работать с ним нам не придется.
  • Файл MainPage.xaml и связанный с ним MainPage.xaml.cs/vb это основная страница приложения. Отличие от приложений WPF заключается в том, что здесь мы работаем не с окнами, а со страницами. Окно у приложения UWP чаще всего одно, и в нем загружаются страницы приложения, между которыми вы переключаетесь, подобно переходу по страницам сайта в браузере. Подробнее о страницах и навигации в UWP я расскажу в одной из ближайших статей.
  • И последний, автоматически созданный фал проекта, — это файл Package.appxmanifest. Это, как вы поняли, манифест проекта, который содержит основные объявления. Этот файл имеет удобный редактор, который вызывается двойным щелчком мыши. В данном редакторе можно выставить важные параметры приложения, задать расположения логотипов, задать возможности приложения и объявить контракты, которые оно будет использовать. По ходу этого цикла я регулярно буду обращаться к разным настройкам манифеста и более подробно их рассматривать. Также замечу, что в документации часто встречается указание, в каких параметрах манифеста какие ключи должны быть отмечены. В этих случаях документация ссылается на текстовую версию манифеста. Открыть ее можно, если нажать правой кнопкой мыши на файл манифеста и выбрать пункт «Открыть с помощью…» и далее — «Редактор (текстовый) XML».

ConvertersAndStyle

  • Файл Converters.cs/vb – это обычный файл «класс», в котором потом помещаются конвертеры, используемые в приложении.
  • Файл ConverterDictionary.xaml – это файл типа «Словарь ресурсов», в котором мы будем записывать ссылки на наши конвертеры. Так как большая часть конвертеров будет использоваться во всем приложении, то и определять их лучше в одном файле, а не в ресурсах каждой отдельной страницы.
  • Файл ApplicationStyle.xaml также является словарем ресурсов, и в нем мы будем определять все ресурсы, связанные со стилем приложения.

ImagesAssets здесь

Интро

  • Создание проекта. Что нужно заложить с самого начала, чтобы получить максимальное удобство и расширяемость в будущем.
  • Стартовый экран. Более живой и более интересный снаружи, эффективный внутри.
  • Многопользовательские элементы. Идентификация пользователя. Как? Где хранить данные? Сколько это стоит?
  • Структура приложения. Сколько нужно страниц. Переходы между ними.
  • Дизайн и стилизация. Несколько статей посвященных внешнему виду приложения. От подготовки графических материалов, до стилизации элементов управления.
  • Создание собственных элементов управления. Когда имеющегося недостаточно и нужно создавать свое.
  • Фоновые события. Живые плитки и уведомления. Важные элементы взаимодействия с пользователем, которые должны присутствовать в каждом UWP приложении.
  • Монетизация. Виды заработка. Какой способ выбрать и как эффективно интегрировать.
  • Отладка на разных устройствах, разрешениях и соотношениях сторон.
  • Сборка и публикация приложения.
  • Поддержка после публикации. Работа по достижению высоких оценок и положительных отзывов.

Samples by category

Audio, video, and camera

360-degree video playback Adaptive streaming Advanced capture
Advanced casting Audio categories Audio graphs
Background media playback Basic camera app Basic face detection
Basic face tracking Basic media casting Camera face detection
Camera frames Camera preview frame Camera profiles
Camera resolution Camera stream coordinate mapper Camera stream correlation
DASH streaming Direct2D photo adjustment Media editing
Media import Media transport controls MIDI
Playlists PlayReady Processing frames with OpenCV
Simple imaging Spatial audio System media transport controls
Transcoding media Video playback Video playback synchronization
Video stabilization Windows audio session (WASAPI)

Controls, layout, and text

3D Printing 3D Printing from Unity Bottom-up list (XAML)
Clipboard Colored glyphs (DirectWrite) Commanding
Context menu Context menu (XAML) Custom text edit control
Data virtualization Display orientation Downloadable fonts (DirectWrite)
Downloadable fonts (XAML) Drag and drop Focus visuals
Full screen mode Gamepad-style navigation (XAML) Line spacing (DirectWrite)
ListView and GridView Lock screen apps Message dialog
Multiple views OCR Printing
Scaling according to DPI Secondary windows Splash screen
State triggers Tailored multiple views Title bar
UI basics (XAML) User interaction mode WebView control (XAML)
Window resizing

Data

Compression Content indexer Logging
PDF document Serializing and deserializing data x:Bind
x:DeferLoadStrategy XML DOM XmlLite

Deep links and app-to-app communication

App services Jump list customization Remote systems
Sharing content source app Sharing content target app User activities

Devices and sensors

Accelerometer Activity detection sensor AllJoyn consumer experiences
AllJoyn producer experiences Altimeter Background sensors
Barcode scanner Barcode scanner provider Barometer
Bluetooth advertisement Bluetooth Low Energy Cash drawer
Compass Custom HID device Custom sensors
Custom serial device Custom USB device Device enumeration and pairing
General Purpose Input/Output (GPIO) Gyrometer Inclinometer
Inter-Integrated Circuit (I2C) Lamp device Light sensor
Line display Magnetometer Magnetic stripe reader
Near field communication (NFC) NFC enterprise provisioner Orientation sensor
Pedometer POS printer Proximity sensor
Radial controller Relative inclinometer Serial Arduino
Serial Peripheral Interface (SPI) Simple orientation sensor

Files, folders, and libraries

File access File and folder thumbnail File picker
File picker provider File search Folder enumeration
Library management Semantic text query

Globalization and localization

Application resources and localization Calendar Date and time formatting
Globalization preferences Japanese phonetic analysis Language font mapping
Linguistic services Number formatting and parsing Text segmentation
Text suggestions Unicode string processing

Graphics and animation

Animated GIF playback (XAML) Animation metrics Composition visual without framework
Direct2D advanced color image rendering Direct2D custom image effects Direct2D gradient mesh
Direct2D SVG image rendering Transform3D animations

Holographic

Basic hologram Holographic face tracking Holographic mixed reality capture
Holographic spatial mapping Holographic spatial stage Holographic voice input
Spatial interaction source Tag-along hologram
Mixed Reality Model

Identity, security, and encryption

Credential locker Client Device Information Credential picker
Disabling screen capture Enterprise data protection KeyCredentialManager
Lock screen personalization Microsoft Passport and Windows Hello Smart cards
User information UserCertificateStore UserConsentVerifier
Web account management WebAuthenticationBroker

Networking and web services

Background transfer DatagramSocket HttpClient
JSON Mobile broadband Radios
Socket activity trigger stream socket StreamSocket Syndication
USSD protocol WebSocket Wi-Fi Direct
Wi-Fi Direct services Wi-Fi hotspot authentication Wi-Fi scanning

Platform architecture

Custom capabilities In-process component authoring In-process component authoring
Out-of-process component authoring Version adaptive code

Using the samples

The easiest way to use these samples without using Git is to download the zip file containing the current version (using the following link or by clicking the «Download ZIP» button on the repo page). You can then unzip the entire archive and use the samples in Visual Studio.

Notes:

  • Before you unzip the archive, right-click it, select Properties, and then select Unblock.
  • Be sure to unzip the entire archive, and not just individual samples. The samples all depend on the SharedContent folder in the archive.
  • In Visual Studio, the platform target defaults to ARM, so be sure to change that to x64 or x86 if you want to test on a non-ARM device.

The samples use Linked files in Visual Studio to reduce duplication of common files, including sample template files and image assets. These common files are stored in the SharedContent folder at the root of the repository, and are referred to in the project files using links.

Reminder: If you unzip individual samples, they will not build due to references to other portions of the ZIP file that were not unzipped. You must unzip the entire archive if you intend to build the samples.

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

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

Adblock
detector