Осторожно, Modern UI

4c1f17d9a6424d248b349c4a3dcac2d2.jpg


Каждый разработчик Windows Store приложений должен знать гайдлайны.
Guideline в переводе с английского — рекомендации, руководящие указания. Для того, чтобы приложение попало в Store не обязательно следовать рекомендациям, но следовать им желательно. Есть несколько особенностей, или иноземно выражаясь фич (англ. feature), которые желательно иметь каждому приложению. Я решил рассмотреть эти особенности, а заодно сделать шаблон C#/XAML приложения Windows Store, с которого можно начинать разработку. Ведь, так или иначе, часто приходится заходить в разработанные ранее приложения или MSDN, чтобы скопировать код сниппета для определенной функции.
Описанные далее возможности не только сделают ваше приложение соответствующим гайдлайнам, но и украсят его дополнительным функционалом, привлекающим внимание пользователей, а также помогут в продвижении.
Контракт Share
Для того, чтобы пользователь мог отправить e-mail друзьям или поделиться информацией о приложении/игре в социальной сети, в код приложения нужно добавить контракт share. Для того чтобы это сделать следуем следующим действиям.
Добавляем пространство имен:

using Windows.ApplicationModel.DataTransfer;


И в классе страницы добавляем объявление переменной:

private DataTransferManager dataTransferManager;       


Далее переопределяем события захода на страницу и выхода с нее:

protected override void OnNavigatedTo(NavigationEventArgs e)
        {
                //регистрируем страницу как источник share
                this.dataTransferManager = DataTransferManager.GetForCurrentView();
                this.dataTransferManager.DataRequested += new TypedEventHandler(this.DataRequested);
        }
   protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
                // удаляем регистрацию
                this.dataTransferManager.DataRequested -= new TypedEventHandler(this.DataRequested);
        }


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

    private void DataRequested(DataTransferManager sender, DataRequestedEventArgs e)
        {
 Uri dataPackageUri = new Uri("http://apps.microsoft.com/windows/ru-ru/app/mp3/0122ffd9-585f-4b3d-a2ad-571f74231d14");
 DataPackage requestData = e.Request.Data;
 requestData.Properties.Title = "Прикольная игра";
 requestData.SetWebLink(dataPackageUri);
 requestData.Properties.Description = "И здесь добавить какое-то описание.Как правило, текст содержит рекомендацию установить приложение.";
        }


Также можно отправить файл или изображение. Есть вариант, при котором сообщение может быть отправлено в формате HTML.
Поделиться из Windows 8.1 можно вызвав волшебную charm панельку и выбрав в ней вот такой значок:
6dcb4e066ca945b899bf3d19ffb8d130.png
В Windows 10 поделиться контентом можно нажав такой же значок в верхнем левом углу приложения:
ddf09d71dc254b679e5372d51d3a22c2.png
Для того, чтобы открыть окно программно из кода, можно воспользоваться следующей строчкой:

Windows.ApplicationModel.DataTransfer.DataTransferManager.ShowShareUI();


Официальное руководство доступно по ссылке:
Краткое руководство: общий доступ к содержимому (XAML)Live tile
Наверняка вы замечали, что некоторые плитки на стартовом экране изменяются со временем. Взять, к примеру, тайлы новостных сайтов или же тайл приложения «Финансы», который сам обновляет сводки. Некоторые тайлы меняются каждые несколько секунд, привлекая тем самым внимание пользователя. Это так называемые «живые» плитки/тайлы.
Для того, чтобы приложение изменило тайл ему можно послать push уведомление, но можно обновить тайл и из самого приложения.
Для того, чтобы обновить тайл из приложения, первым делом нужно добавить пространство имен

using Windows.UI.Notifications;  


Далее напишем простой метод, который изменит вид и текст тайла:

void UpdateTileWithText()
        {
            //    #  обновление квадратного тайла
            var tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text04);
            var tileAttributes = tileXml.GetElementsByTagName("text");
            string tiletext = "Какой - либо текст для отображения на тайле";
            tileAttributes[0].AppendChild(tileXml.CreateTextNode(tiletext));
            var tileNotification = new TileNotification(tileXml);
            tileNotification.ExpirationTime = DateTimeOffset.UtcNow.AddHours(1);
            TileUpdateManager.CreateTileUpdaterForApplication().Update(tileNotification);
        }


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

По гайдлайнам очень рекомендуется, чтобы у приложения были плитки и квадратного и широкого размера, поэтому желательно этот же код дублировать, указав в виде шаблона тайла уже не квадратный, а широкий шаблон. То есть в примере заменить TileTemplateType.TileSquare150×150Text04 на TileTemplateType.TileWide310×150Text04.

У себя в приложении я обновлял тайл при событии App_Suspending, для того, чтобы напомнить пользователям на чем они остановились, но можно делать это в любой другой момент.
Если нужно очистить изменения, которые были совершены и вернуть тайл к первоначальному виду, то сделать это можно из кода строчкой:

TileUpdateManager.CreateTileUpdaterForApplication().Clear();


Официальная, хоть и краткая, но чуть более полная инструкция доступна по ссылке:
Краткое руководство: отправка обновления плитки (XAML)Rate and Review
Рекомендуется ненавязчиво предлагать пользователям оценить ваше приложение. Хорошие оценки и отзывы помогут повысить популярность вашего предложения. Кроме того отзывы пользователей позволяют вам своевременно и с пользой делать изменения функционала и дизайна приложения. Для того, чтобы открыть окно Windows Store с оценкой достаточно создать и открыть URI. Для этого достаточно двух строчек:

 var uri = new Uri("ms-windows-store:Review?PFN=9cc1e6dd-9d82-4736-aee5-acb9a01d9c39_1dv79ndb6c382");
 await Windows.System.Launcher.LaunchUriAsync(uri);


Обратите внимание на то, что открытие страницы происходит асинхронно с использованием await. Раз так, то к процедуре нажатия кнопки необходимо будет добавить предикат async.
Сформировать URI относительно просто. К тексту «ms-windows-store: Review? PFN=» нужно добавить Package Family Name или сокращенно PFN. Его значение можно узнать, открыв манифест приложения.
754d6222009047f287e7220e986db3d3.PNG
Ссылка на официальное руководство как сформировать ссылку на приложение в Store:
Linking to your app
Ссылку указал на английском, так как в русском переводе перевели по ошибке еще и ключевые слова.

Так как шаблон мы пишем под 8.1, а не под 10, то есть одна небольшая путаница. Способ формирования URI для WP 8.1 немного отличается от способа формирования URI для Windows Store приложений. Для WP 8.1 URI выглядит вот так:
ms-windows-store: reviewapp? appid=cq23k522–7u59–1193-h4aa-3t56e4633c24
Официальное руководство (на русском):
Ссылка на ваше приложение в Магазине

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

Settings
Простой сниппет, с помощью которого можно считать сколько раз приложение было запущено:
В объявления переменных добавим:

int appRunCount = 0;
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;


В конструктор класса страницы после this.InitializeComponent (); добавим:

            try
            {
                appRunCount = (int)localSettings.Values["AppRunCount"];
            }
            catch { }

            appRunCount++;

            try
            {
                localSettings.Values["AppRunCount"] = appRunCount;
            }
            catch { }


Таким образом мы получим в переменной appRunCount количество запусков приложения.
Вместо Windows.Storage.ApplicationData.Current.LocalSettings мы можем использовать Windows.Storage.ApplicationData.Current.RoamingSettings. Если сделать так, то мы сможем сохранять настройки не локально на устройстве, а в роуминге, т.е. в сети. Они сохраняются в пользовательском аккаунте Microsoft. RoamingSettings будут доступны с любого устройства, на котором был совершен вход из одного и того же аккаунта.
Простой код, которым выдается сообщение в случае, если приложение запущено 5-ый раз и в случае согласия пользователя поставить оценку открывается окошко магазина с предложением оставить отзыв:

  if (appRunCount == 5)
            {
   var messageDialog = new Windows.UI.Popups.MessageDialog("Оставьте, пожалуйста, отзыв о приложении", "Проголосуйте за нас!");
     // можем добавить не больше трех команд/вариантов выбора 
   messageDialog.Commands.Add(new Windows.UI.Popups.UICommand("Поставить оценку", new Windows.UI.Popups.UICommandInvokedHandler(CommandHandler)));
   messageDialog.Commands.Add(new Windows.UI.Popups.UICommand("Я уже ставил оценку", new Windows.UI.Popups.UICommandInvokedHandler(CommandHandler)));
   messageDialog.Commands.Add(new Windows.UI.Popups.UICommand("В другой раз", new Windows.UI.Popups.UICommandInvokedHandler(CommandHandler)));

   messageDialog.DefaultCommandIndex = 0;
   messageDialog.CancelCommandIndex = 2;
   await messageDialog.ShowAsync();
            }

       private async void CommandHandler(IUICommand command)
        {
            if (command.Label=="Поставить оценку")
            {
     var uri = new Uri("ms-windows-store:PDP?PFN=9cc1e6dd-9d82-4736-aee5-acb9a01d9c39_1dv79ndb6c382");
     await Windows.System.Launcher.LaunchUriAsync(uri);
            }
        }


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

Вот где можно почитать официальное руководство:
Загрузка и сохранение параметров

Для того, чтобы пользователь мог изменить какие-то настройки в Modern UI приложениях есть возможность создать «вылетающую» панельку — Flyout

Settings Flyout
Такая возможность доступна только для приложений Windows 8.1 и 10. В Windows 8 при желании создать аналогичную панельку было возможно, но необходимо было создавать свой user control.
Для того, чтобы добавить в приложение «вылетающую» панельку с настройками в проект необходимо добавить новый элемент управления под названием Settings Flyout (в русскоязычном варианте «Всплывающий элемент параметров»). Порядок действий следующий. Заходим в меню:
Project — Add New Item… — Visual C# — XAML — Settings Flyout
или
Проект — Добавить новый элемент — Visual C# — XAML — Всплывающий элемент параметров
Назовем новый элемент, например, так: CustomSettingsFlyout.xaml
Добавляем в App.xaml.cs приложения ссылки на пространства имен:

using Windows.UI.ApplicationSettings;
using Windows.UI.Popups;


И следующий код:

        protected override void OnWindowCreated(WindowCreatedEventArgs args)
        {
            SettingsPane.GetForCurrentView().CommandsRequested += OnCommandsRequested;
        }

        private void OnCommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
        {
            SettingsCommand settingsCommand = new SettingsCommand("SettingsPage", "Open settings",new UICommandInvokedHandler(onSettingsCommand));
            args.Request.ApplicationCommands.Add(settingsCommand);
        }

        private void onSettingsCommand(IUICommand command)
        {
            CustomSettingsFlyout settingsFlyout = new CustomSettingsFlyout();
            settingsFlyout.Show();
        }


Теперь при вызове настроек приложения у нас будет отображено наше окно. Можем править код XAML и C# нашего элемента CustomSettingsFlyout так как нам нужно.
Сохранять настройки мы только что научились с помощью класса Windows.Storage.ApplicationData.Current.LocalSettings

Официальный мануал:
Краткое руководство: добавление параметров приложения (XAML)

Всплывающие уведомления
Для того, чтобы уведомить пользователя о чем-либо, можно отобразить toast уведомление. Это небольшой прямоугольник с картинкой и текстом, которые выплывает справа, подобно Flyout. Toast уведомление не блокирует интерфейс приложения в отличие от MessageBox-а. Довольно удобно будет, если у нас в коде вызов уведомления будет заключен в отдельном методе. Добавляем еще 2 пространства имен:

using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;


И добавим сам метод, после вызова которого с текстом в качестве параметра мы получим уведомление:

        void ShowToast(string whattext)
        {
            XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            XmlNodeList stringElements = toastXml.GetElementsByTagName("text");
            stringElements[0].AppendChild(toastXml.CreateTextNode(whattext));
            ToastNotification toast = new ToastNotification(toastXml);

            toast.Activated += ToastActivated;
            toast.Dismissed += ToastDismissed;
            toast.Failed += ToastFailed;

            ToastNotificationManager.CreateToastNotifier().Show(toast);
        }


Первой строкой мы задаем значением xml шаблон ToastText01. Это довольно простой шаблон, который содержит в себе только текст, занимающий 3 строки.
Все возможные шаблоны здесь: Каталог шаблонов всплывающих уведомлений
Еще вы можете заметить, что мы подписываемся на 3 события: активацию уведомления, скрытие уведомления и ошибку уведомления. Теперь на обязательно нужно реализовать обработчики этих событий (пусть даже и без кода):

        private void ToastFailed(ToastNotification sender, ToastFailedEventArgs args) { }
        private void ToastDismissed(ToastNotification sender, ToastDismissedEventArgs args) { }
        private void ToastActivated(ToastNotification sender, object args) { }


Официальное руководство:
Краткое руководство: отправка всплывающего уведомления (XAML)AppBar и CommandBar
Напоследок, добавим в приложение панель со стандартными элементами управления.
Панель может быть верхней или нижней. Кнопки команд и инструментов принято размещать на нижней панели.
Панель можно создать в XAML следующими тэгами:


        



Или


        



Содержимым панели может быть элемент AppBar (для различных контролов, кои ваша душенька пожелает разместить) или элемент CommandBar (только для кнопок — XAML элементов AppBarButton, AppBarToggleButton и AppBarSeparator). Для обычного приложения вполне достаточно обычных кнопок, поэтому ограничимся CommandBar-ом. Код такой:

    
        
            
            

            
                
            
        
    


Обратите внимание на атрибут IsOpen=«True». При открытии приложения желательно отобразить панель, дабы пользователь был в курсе ее наличия и соответственно знал какие возможности есть у приложения. Также вы можете заметить вложенный тег CommandBar.SecondaryCommands которые содержит в себе кнопки, которые будут отражены слева панели. Они как бы второстепенные.

Официальное руководство:
Краткое руководство: добавление панелей приложения (XAML)

Secondary tile
Есть возможность разрешить пользователю закрепить вспомогательную плитку/тайл на стартовый экран Windows. По нажатию этой плитки приложение может открываться с определенными параметрами, также вспомогательный тайл может быть «живым» (т.е. live тайлом) и отображать какие-либо специальные оповещения.
Сперва, чтобы добавить secondary tile, мы добавим необходимое отсутствующее пространство имен:

using Windows.UI.StartScreen;


в конструктор страницы после InitializeComponent (); добавляем вызов метода с параметром:

ToggleAppBarButton(!SecondaryTile.Exists("MyUnicTileID"));


Здесь MyUnicTileID это уникальный идентификатор тайла
Далее нам нужно добавить сам метод ToggleAppBarButton, который будет отображать значок прикрепить или открепить в зависимости от текущего состояния вспомогательной плитки.

   public void ToggleAppBarButton(bool showPinButton)
        {
            if (showPinButton)
            {
                btnSecTile.Label = "Прикрепить";
                btnSecTile.Icon = new SymbolIcon(Symbol.Pin);
            }
            else
            {
                btnSecTile.Label = "Открепить";
                btnSecTile.Icon = new SymbolIcon(Symbol.UnPin);
            }
            this.btnSecTile.UpdateLayout();
        }


Здесь showPinButton это булева переменная, которая хранит значение передаваемое! SecondaryTile.Exists («MyUnicTileID»), т.е. прикреплен ли вспомогательный тайл приложения к стартовому экрану или нет.
Теперь добавим код в событие нажатия кнопки. Этот код будет прикреплять плитку к начальному экрану или откреплять ее:

    private async void btnSecTile_Click(object sender, RoutedEventArgs e)
        {
    Windows.Foundation.Rect rect = GetElementRect((FrameworkElement)sender);
           
            if (SecondaryTile.Exists("MyUnicTileID"))
            {
                SecondaryTile secondaryTile = new SecondaryTile("MyUnicTileID");

                bool isUnpinned = await secondaryTile.RequestDeleteForSelectionAsync(rect, Windows.UI.Popups.Placement.Above);
                ToggleAppBarButton(isUnpinned);
            }
            else
            {
                // Pin
                Uri square150x150Logo = new Uri("ms-appx:///Assets/Logo.scale-100.png");
                string tileActivationArguments = "Secondary tile was pinned at = " + DateTime.Now.ToLocalTime().ToString();
                string displayName = "Application name";

                TileSize newTileDesiredSize = TileSize.Square150x150;
                SecondaryTile secondaryTile = new SecondaryTile("MyUnicTileID",
                                                                displayName,
                                                                tileActivationArguments,
                                                                square150x150Logo,
                                                                newTileDesiredSize);

                secondaryTile.VisualElements.Square30x30Logo = new Uri("ms-appx:///Assets/SmallLogo.scale-100.png");
                secondaryTile.VisualElements.ShowNameOnSquare150x150Logo = true;
                secondaryTile.VisualElements.ForegroundText = ForegroundText.Light;
                bool isPinned = await secondaryTile.RequestCreateForSelectionAsync(rect, Windows.UI.Popups.Placement.Above);
                ToggleAppBarButton(!isPinned);
            }
        }


Также вам нужно добавить функцию

        public static Rect GetElementRect(FrameworkElement element)
        {
            GeneralTransform buttonTransform = element.TransformToVisual(null);
            Point point = buttonTransform.TransformPoint(new Point());
            return new Rect(point, new Size(element.ActualWidth, element.ActualHeight));
        }


Примерно такое вот предупреждение вы должны получить при закреплении плитки на начальный экран:
533dc754d42c4f8885b32537601e0eb7.jpg
«App Template» — это название приложения. Вы можете или закрепить плитку или отказаться, кликнув где-либо свободном месте приложения и закрыв тем самым pop-up.
Как обычно, ссылка на официальное руководство:
Краткое руководство. Закрепление вспомогательной плитки (XAML)

Это были некоторые из возможностей Windows Store приложений. Очень рекомендую их использовать.
Получившийся шаблон вы можете скачать по ссылке с GitHub:
https://github.com/programmersommer/WindowsStoreAppTemplate
или в качестве архива zip (версия с русскими комментариями):
OneDrive

© Habrahabr.ru