Pull to refresh
97.64
Rating
Microsoft
Microsoft — мировой лидер в области ПО и ИТ-услуг

Fall Creators Update: важное для программиста

Microsoft corporate blog Programming *.NET *C# *
Классические дотнетовские приложения хороши тем, что они практически не ограничены в правах и, например, могут работать в трее. Зато универсальные приложения (UWP) более безопасны, и их можно устанавливать и удалять бесчисленное количество раз, не забивая систему и реестр мусором. Платформа UWP постоянно развивается, и, пока пользователи обновляются до Fall Creators Update, который вышел в октябре этого года, мы, разработчики, можем посмотреть на его новые и интересные возможности.



Готов? Скачивай последнюю SDK с официальной страницы, и начнем нашу ознакомительную экскурсию.

Примечание: мы продолжаем серию публикаций полных версий статей из журнала Хакер. Орфография и пунктуация автора сохранены.

В первую очередь хотелось бы заметить про множественные улучшения в дизайнере XAML. Одним из самых ожидаемых улучшений для меня является повышение скорости работы. Сравните скорость загрузки в Fall Creators Update (слева) с простым Creators Update:



На конференции Build 2017 Microsoft анонсировала новую систему UI дизайна под названием Fluent.



И вот начиная с этого обновления в UWP начнут появляться новые элементы управления, основанные на этой системе.

Navigation View


Это out of box контрол для отображения меню.



Меню выпадает с левой стороны. Кроме того, к меню относится и полоска сверху — Header. На эту полоску можно вынести какой-то текст заголовка или какие-то дополнительные кнопки.
Меню может использоваться в 3-ех различных вариациях. Вариант отображенный сверху это Minimal. В этом режиме Header скрыть нельзя, так как на нем находится кнопка «гамбургер». Есть еще режим Compact в котором справа отображаются иконки меню.



В режиме Expanded меню отображается раскрытым.

Изменяя размер окна вашего приложения вы можете изменить режим Navigation View. Ведь система автоматически выбирает режим исходя из размера окна приложения. На этот выбор можно повлиять, указав различные значения пикселей атрибутам OpenPaneLength, CompactModeThresholdWidth и ExpandedModeThresholdWidth.

Пример кода панели навигации:

 <NavigationView x:Name="NavView" IsSettingsVisible="True"
                    ItemInvoked="NavView_ItemInvoked">

        <NavigationView.MenuItems>
            <NavigationViewItem Content="Начальная страница" Tag="home">
                <NavigationViewItem.Icon>
                    <FontIcon Glyph=""/>
                </NavigationViewItem.Icon>
            </NavigationViewItem>
            <NavigationViewItemSeparator/>
            <NavigationViewItemHeader Content="Новые возможности"/>
            <NavigationViewItem Icon="AllApps" Content="Автозагрузка" Tag="автозагрузка"/>
            <NavigationViewItem Icon="AllApps" Content="Перезапуск" Tag="перезапуск"/>
            <NavigationViewItem Icon="Video" Content="Color picker" Tag="color picker"/>
            <NavigationViewItem Icon="Audio" Content="Parallax" Tag="parallax"/>
            <NavigationViewItem Icon="Audio" Content="Другие контролы" Tag="другие"/>
        </NavigationView.MenuItems>

        <NavigationView.HeaderTemplate>
            <DataTemplate>
                <Grid Background="LightGray">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Style="{StaticResource TitleTextBlockStyle}"
                           FontSize="28"
                           VerticalAlignment="Center"
                           Margin="12,0"
                           Text="Это Header"/>
                    <CommandBar Grid.Column="1"
                            HorizontalAlignment="Right"
                            DefaultLabelPosition="Right">
                        <AppBarButton Label="Дополнителная кнопка" Icon="Refresh"/>
                    </CommandBar>
                </Grid>
            </DataTemplate>
        </NavigationView.HeaderTemplate>

        <NavigationView.PaneFooter>
            <Image Source="Assets/logo.png" Width="50" Height="50" />
        </NavigationView.PaneFooter>

        <Frame x:Name="ContentFrame">
            <Frame.ContentTransitions>
                <TransitionCollection>
                    <NavigationThemeTransition/>
                </TransitionCollection>
            </Frame.ContentTransitions>
        </Frame>

    </NavigationView>



Обратите внимание, что есть возможность добавить вниз какие-нибудь произвольные контролы. В примере туда добавлена картинка (кубик над пунктом меню Settings/Настройки). Сам пункт меню Settings включается и выключается с помощью атрибута IsSettingsVisible.

В коде C# в событии NavView_ItemInvoked можно проверить была ли нажата кнопка Settings.

if (args.IsSettingsInvoked)
     {
         ContentFrame.Navigate(typeof(SettingsPage));
     }

Или же можно проверить содержимое args.InvokedItem, которое содержит в себе текст нажатого элемента пункта меню. Например, так:

  if (args.InvokedItem==”Начальная страница”)
     {
         ContentFrame.Navigate(typeof(HomePage));
     }

Более подробную информацию смотрите на официальной страничке документации.

Person Picture Control


Элемент управления, отображающий аватар и имя/инициалы пользователя. Довольно простой контрол.



Добавить на страницу его можно с помощью следующего тега:

    <PersonPicture DisplayName="John Doe" Foreground="Black" ProfilePicture="Assets\johndoe.jpg" Initials="JD" />

Его рекомендуется использовать для отображения аватарки текущего пользователя или какого-либо контакта.

Подробнее почитать о нем можно здесь.

Rating Control


С этим контролом тоже все должно быть понятно.



Добавить на страницу можно следующим тегом:

    <RatingControl x:Name="MyRatings" />

Официальная документация тут.

Color Picker


Долгожданный контрол для выбора цвета.



В следующем примере при изменении цвета в контроле автоматически меняется цвет фона (используется простая привязка или выражаясь иначе — биндинг).

     <Grid>
        <Grid.Background>
            <SolidColorBrush Color="{x:Bind myColorPicker.Color, Mode=OneWay}"/>
        </Grid.Background>
        <ColorPicker x:Name="myColorPicker" />
    </Grid>

Официальная документация

Parallax


Неравномерное перемещение объектов при прокрутке позволяет создать эффект параллакса.



Допустим у вас есть Grid внутри которого размещен какой-то элемент, содержимое которого не помещается на одной странице. И фоном в Grid добавлено какое-то изображение. Для того чтобы появился эффект параллакса необходимо изображение обернуть в тег Parallax, указав в качестве Source привязку к очень-очень длинному контенту.

В следующем примере ListView с именем ForegroundElement не умещается на экране. Фоном ему установлено изображение и при прокрутке возникнет красивый эффект.

<Grid>
        <ParallaxView Source="{x:Bind ForegroundElement}" VerticalShift="50">
            <!-- Фон -->
            <Image x:Name="BackgroundImage" Source="Assets/background.jpg"
               Stretch="UniformToFill"/>
        </ParallaxView>

        <ListView x:Name="ForegroundElement">
            <x:String>Item 1</x:String>
            <x:String>Item 2</x:String>
            <x:String>Item 3</x:String>
            <x:String>Item 4</x:String>
            <x:String>Item 5</x:String>
            <x:String>Item 6</x:String>
            <x:String>Item 7</x:String>
            <x:String>Item 8</x:String>
            <x:String>Item 9</x:String>
            <x:String>Item 10</x:String>
            <x:String>Item 11</x:String>
            <x:String>Item 13</x:String>
            <x:String>Item 14</x:String>
            <x:String>Item 15</x:String>
            <x:String>Item 16</x:String>
            <x:String>Item 17</x:String>
            <x:String>Item 18</x:String>
            <x:String>Item 19</x:String>
            <x:String>Item 20</x:String>
            <x:String>Item 21</x:String>
        </ListView>
    </Grid>

Подробнее читайте в документации Microsoft.

Swipe


Еще одним интересным контролом является SwipeControl. Возможно, что вы встречали его раньше в каких-либо приложениях. Он позволяет с помощью одноименного жеста открыть пункт меню. Жестом является движение пальца слева на право или наоборот. Посмотрите на следующий скриншот и вам станет понятнее о чем речь.



INFO


Режим Reveal означает, что после жеста будет отображен пункт скрытый меню. Альтернативно можно установить режим Execute, который сразу же не только отобразит, но и выполнит действие меню.

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

<Page.Resources>
        <SymbolIconSource x:Key="DeleteIcon" Symbol="Delete" />

        <SwipeItems x:Key="ExecuteDelete" Mode="Reveal">
            <SwipeItem Text="Delete" IconSource="{StaticResource DeleteIcon}" Invoked="SwipeDeleteItem_Invoked" />
        </SwipeItems>
    </Page.Resources>

В нем мы создаем иконку с символом корзины и ключом «DeleteIcon». Далее создаем пункт меню Swipe с ключом «ExecuteDelete» и только что созданной иконкой. По нажатию на этот пункт меню будет вызвано событие SwipeDeleteItem_Invoked.

Теперь рассмотрим XAML код списка:

    <ListView x:Name="sampleList" Width="400" Height="300">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="x:String">
                <SwipeControl
                 RightItems="{StaticResource ExecuteDelete}">
                    <StackPanel Orientation="Vertical" Margin="5">
                        <TextBlock Text="{x:Bind}" FontSize="18"/>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit..." FontSize="12"/>
                        </StackPanel>
                    </StackPanel>
                </SwipeControl>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.Items>
            <x:String>Demo item 1</x:String>
            <x:String>Demo item 2</x:String>
            <x:String>Demo item 3</x:String>
        </ListView.Items>
    </ListView>

Как вы можете заметить, в ListView добавлено 3 пункта с названиями «Demo item ..». Для простоты они добавлены прямо в список, но можно привязать ListView к какой-нибудь коллекции с помощью биндинга.

Самому списку назначен шаблон, в котором используется SwipeControl с ресурсом ExecuteDelete. Контрол будет отображен при жесте справа на лево так как используется атрибут RightItems.

Можно обойтись и без ListView. Например, так:

    <SwipeControl Width="400" Height="75"
          RightItems="{StaticResource ExecuteDelete}">
         <StackPanel Orientation="Vertical" Margin="5" Background="DarkGray">
             <TextBlock Text="Какой-нибудь заголовок" FontSize="18"/>
             <StackPanel Orientation="Horizontal">
                 <TextBlock Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit..." FontSize="12"/>
             </StackPanel>
         </StackPanel>
     </SwipeControl>

Таким образом вы сможете добавить скрытое меню, отображаемое жестом, какому-нибудь элементу вашей страницы.

Официальная документация здесь.

Acrylic Material


Это даже не совсем элемент управления. Это кисть, которая довольно часто используется в интерфейсах. Меню «Пуск» в Fall Creators Update выполнено из акрила. Вот так выглядит стандартное приложение «Калькулятор» с фоном из акрилового материала:



XAML код этой кисти может выглядеть примерно так:

<AcrylicBrush TintColor="#ED3462ED" TintOpacity="0.8" FallbackColor="#ADAFAFFF"/>

Больше информации найдете на сайте microsoft.com.

Reveal


Опять не контрол, а определенный световой эффект, который позволяет обратить внимание пользователя на тех объектах, которые находятся в фокусе курсора.



Некоторые контролы поддерживают reveal по умолчанию. Это ListView, GridView, TreeView, NavigationView, AutosuggestBox, MediaTransportControl, CommandBar, ComboBox.

А на некотрых контролах этот эффект можно включить, указав особый стиль. Например, это можно указать кнопке:

    <Button Content="Button Content" Style="{StaticResource ButtonRevealStyle}"/>

Документация.

Еще одно улучшение в дизайнере XAML


Разумеется, что дизайнер Visual Studio позволяет отображать эти контролы и оптимизирован для их отображения. На следующем изображении вы можете увидеть, как в дизайнере отображен ресурс AcrylicBrush (Fall Creators Update опять слева).



Почитать про улучшения XAML дизайнера на английском с кучей технических деталей и уточнений можно здесь: A significant update to the XAML Designer.

.NET Standard 2.0


Большим шагом вперед является поддержка .NET Standard 2.0. Но для него необходимо, чтобы у вашего проекта минимальной версией был установлена версия билда выше чем 1627. Зато теперь портировать код .NET Framework приложений на UWP станет гораздо проще.

Автозапуск приложения


Одной из самых интересных возможностей является возможность запускать приложение при запуске операционной системы. Раньше такая возможность была у Desktop Bridge приложений, но у UWP приложений ее не было.

Настроим манифест. Приложение должно использовать namespace контракт 5-ой версии:

    xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"

И необходимо зарегистрировать расширение windows.startupTask.

    <uap5:Extension
    Category="windows.startupTask"
    Executable="App1.exe"
    EntryPoint="App1.App">
    <uap5:StartupTask
    TaskId="SomeIdThatIUseWithThisApp"
    Enabled="false"
    DisplayName="Name of Test App" />
    </uap5:Extension>

Иерархия манифеста следующая: Package Applications Application Extensions <uap5:Extension>

Зарегистрировать автозапуск приложения можно с помощью подобного кода:

    // Сначала проверяем состояние автозапуска. Получаем его в переменную startupTask
    StartupTask startupTask = await StartupTask.GetAsync("SomeIdThatIUseWithThisApp");
    switch (startupTask.State)
    {
        case StartupTaskState.Disabled:
            // В случае если автозапуск просто выключен пробуем его включить
            StartupTaskState newState = await startupTask.RequestEnableAsync();
           // в переменной newState будет получен результат того было ли включение автозапуска благополучным
            break;
        case StartupTaskState.DisabledByUser:
            // Здесь автоматически включить автозапуск не получится. Раз выключено пользователем, то значит он автоматически его не хочет включать…
            break;
        case StartupTaskState.DisabledByPolicy:
	// автозапуск выключен групповыми политиками или не поддерживается устройством
            break;
        case StartupTaskState.Enabled:
            // все уже включено :)
            break;
    }

Этот код требует добавления следующего пространства имен:

    using Windows.ApplicationModel;

INFO


По умолчанию после установки приложения автозапуск выключен.

Если ваше приложение поддерживает автозапуск, то вы можете перегрузить метод OnActivated и получить какие-то параметры. Примерно таким образом:

    protected override void OnActivated(IActivatedEventArgs args)
    {
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
    }

    if (args.Kind == ActivationKind.StartupTask)
    { 
      // здесь вы можете получить аргументы автозапуска
        var startupArgs = args as StartupTaskActivatedEventArgs;
    }
 
    rootFrame.Navigate(typeof(MainPage));
    Window.Current.Activate();
    }

Почитать про этот функционал на английском можно здесь: Configure your app to start at log-in

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


Еще одним, как говорится, «из той же серии» функционалом является возможность перезапуска приложения. Предполагается, что это может быть необходимо для перезапуска игры/приложения после обновления лицензии или установки какого-то дополнительного контента.

Делается перезапуск одной строчкой:

    AppRestartFailureReason result = await CoreApplication.RequestRestartAsync("строка с какими-нибудь параметрами, которые можно считать при активации приложения");

И добавлением пространства имен:

    using Windows.ApplicationModel.Core;

Возвращаемым значением переменной result может быть одно из значений APPRestartFailureReason: NotInForeground, RestartPending, Other

WARNING


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

Еще есть возможность перезапустить приложение в контексте другого пользователя с помощью RequestRestartForUserAsync.

Пример перезапускающегося приложения находится по следующей ссылке Request Restart Sample.

Английский артикул тут: How to Restart your App Programmatically.

WWW


В результате того что я все попробовал на практике, у меня получилось простенькое и веселенькое приложение в котором используется перечисленный в этой статье функционал. Посмотреть его код вы можете по ссылке: GitHub репозиторий FallCreatorsApp.

В заключение, хотелось бы заметить, что не так давно вышел в свет UWP-шный WinDbg.

Обычные дебаггеры позволяют двигаться только вперед по времени выполнения кода. А у этого есть функционал под названием Time Travel Debugging (TTD), с помощью которой можно вернуться назад по процессу исполнения кода. Интересно, что код можно выполнить на определенной машине (именно на той, на которой возникает баг) и записать процесс исполнения кода. Будет создан trace файл с расширением .RUN. Этот файл можно проигрывать множество раз и анализировать.

Заключение


Напоминаю, что UWP приложения лучше олдскульных .NET-овских тем, что они более безопасны и их можно устанавливать/удалять бесчисленное количество раз не забивая систему/реестр различным мусором. Хотя и у классических дотнетовских приложений тоже пока что есть свои плюсы. Они практически неограничены в правах. Или же, например, могут работать в трее. Но скоро эти плюсы могут появиться и у UWP.

Напоминаем, что это полная версия статьи из журнала Хакер. Ее автор — Алексей Соммер.
Tags:
Hubs:
Total votes 23: ↑23 and ↓0 +23
Views 12K
Comments Comments 62

Information

Founded
Location
США
Website
www.microsoft.com
Employees
Unknown
Registered