Как и большинство разработчиков, я наблюдал за развитием Windows 10 и переваривал весь функционал, который Microsoft предоставила нам на конференции BUILD. И теперь я готов создавать UWP приложения (Universal Windows Platform). UWP это новая модель, которая позволяет писать приложения для широкого диапазона устройств Windows: настольных ПК, планшетов, телефонов, Xboxes, устройств IoT и даже HoloLens. Это будущее разработки.
В отличие от универсальных приложений для Windows 8.1, универсальные приложения для Windows 10 действительно являются универсальными. В Windows 8.1 универсальное приложение состояло (в Visual Studio), как правило, из одного общего проекта, двух “главных” и вспомогательных. В итоге построения решения производилось два двоичных файла: один для Windows и один для Windows Phone. В то время, как общий проект содержал общий код, который работал на обоих платформах, пользовательский интерфейс вы создали отдельно, как для Windows, так и для Windows Phone.
В Windows 10 все меняется и универсальность проявляется не только частично, а во всей своей красоте. В итоге, при построении мы получаем один двоичный файл — пакет APPX, который работает на любом устройстве UWP. К тому же у нас теперь не будет минимальных трех проектов (общий и два “главных”) — проект универсального UWP приложения содержит только один “главный” проект. Именно из-за этого ведется большое количество разговоров вокруг разработки адаптивных интерфейсов для такого рода приложений. Так как интерфейс, который хорошо выглядит на телефоне, скорее всего, не будет хорошо смотреться на 30″ настольном мониторе (и наоборот).
Одним из инструментов, который дает нам Microsoft для построения адаптивных интерфейсов в UWP приложениях является AdaptiveTrigger. У AdaptiveTrigger есть два главных и важных свойства: MinWindowWidth и MinWindowHeight. Вы можете использовать AdaptiveTrigger в сочетании с Visual State Manager и адаптировать пользовательский интерфейс для экранов различных размеров. Например, вы могли бы расположить основные части интерфейса горизонтально, но сделать выбор в пользу вертикальной планировки для телефонов. Благодаря AdaptiveTrigger и Visual State Manager вы можете сделать это в XAML без написания единой строки (C #) кода.
Ниже приведен простенький пример использование AdaptiveTrigger для изменения цвет фона элемента при изменении размера окна/экрана. Предположим, что ваша страница содержит базовый элемент (например Grid) с именем LayoutRoot, который растягивается на всю ширину и высоту страницы, и вы хотите установить цвет фона этого элемента до светло-желтого или светло-зеленый, в зависимости от ширины страницы , Вот то что вам понадобится для этого:
<VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="WindowStates"> <VisualState x:Name="WideState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="800" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="LightYellow" /> </VisualState.Setters> </VisualState> <VisualState x:Name="NarrowState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="LightGreen" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>
Теперь фон будет светло-желтого цвета, когда ширина больше или равна 800 пикселям, а светло-зеленым, когда меньше. Вы можете попробовать данный код на настольном ПК Windows и вы увидите, что фон изменяется в реальном времени, когда ширина окна пересекает порог в 800 пикселей. Также обратите внимание на новое свойство сеттеров у VisualState элемента. Вместо того, чтобы использовать анимацию для изменения состояния, теперь вы можете использовать сеттеры для присвоения значений свойств напрямую. Это делает ваш XAML чище и более интуитивнее.
Чтобы показать более практическое применение AdaptiveTrigger, есть небольшое приложение, который вы можете скачать с OneDrive. Вот как это выглядит:
Один интерфейс определяется в одном XAML файле (MainPage.xaml), но интерфейс адаптируется к размерам экрана. Когда ширина экрана/окна больше или равна 800 пикселям — три основных составляющих макета (панель, содержащая рецепт, описание и изображение, панель с ингредиентами, и третья) — расположены бок о бок , Но когда ширина меньше 800 пикселей, пользовательский интерфейс изменяется так, чтобы три панели располагались друг под другом. (На скриншоте эмулятора вы можете видеть только верхнюю панель. Все три панели лежат в ScrollViewer, так что вы можете прокручивать вниз).
Далее необходимый нам XAML:
<Page x:Class="AdaptiveTriggerDemo.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AdaptiveTriggerDemo" xmlns:comp="using:AdaptiveTriggerDemo.Components" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <comp:ListConverter x:Key="ListConverter" /> </Page.Resources> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Margin="24,17,0,28"> <TextBlock Text="Contoso Cookbook" Foreground="#C33D27" Style="{ThemeResource TitleTextBlockStyle}" Typography.Capitals="SmallCaps"/> <TextBlock Text="{Binding Title}" Margin="0,8,0,0" Style="{ThemeResource SubheaderTextBlockStyle}" TextWrapping="WrapWholeWords"/> </StackPanel> <ScrollViewer Grid.Row="1"> <Grid Margin="0,-24,24,24"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <StackPanel x:Name="ImagePanel" Margin="24,24,0,0"> <Image Source="{Binding ImagePath}" HorizontalAlignment="Left" /> <TextBlock Text="{Binding Description}" FontSize="20" FontWeight="Light" TextWrapping="WrapWholeWords" Margin="0,8,0,8" /> <StackPanel Orientation="Horizontal"> <TextBlock FontSize="24" FontWeight="Light" Foreground="#C33D27" Text="{Binding PrepTime}" Margin="0,0,8,0"/> <TextBlock FontSize="24" FontWeight="Light" Foreground="#C33D27" Text="minutes"/> </StackPanel> </StackPanel> <StackPanel x:Name="IngredientsPanel" Margin="24,24,0,0"> <Rectangle Height="32" Fill="#C33D27" /> <TextBlock FontSize="26" Foreground="#C33D27" FontWeight="Light" Text="Ingredients" Margin="0,24,0,8"/> <TextBlock FontSize="16" FontWeight="Light" Text="{Binding Ingredients, Converter={StaticResource ListConverter}}" TextWrapping="Wrap" /> </StackPanel> <StackPanel x:Name="DirectionsPanel" Margin="24,24,0,0"> <Rectangle Height="32" Fill="#C33D27" /> <TextBlock FontSize="26" Foreground="#C33D27" FontWeight="Light" Text="Directions" Margin="0,24,0,8"/> <TextBlock FontSize="16" FontWeight="Light" Text="{Binding Directions}" TextWrapping="Wrap" /> </StackPanel> </Grid> </ScrollViewer> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="WindowStates"> <VisualState x:Name="WideState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="800" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="IngredientsPanel.(Grid.Row)" Value="0" /> <Setter Target="IngredientsPanel.(Grid.Column)" Value="1" /> <Setter Target="DirectionsPanel.(Grid.Row)" Value="0" /> <Setter Target="DirectionsPanel.(Grid.Column)" Value="2" /> <Setter Target="ImagePanel.(Grid.ColumnSpan)" Value="1" /> <Setter Target="IngredientsPanel.(Grid.ColumnSpan)" Value="1" /> <Setter Target="DirectionsPanel.(Grid.ColumnSpan)" Value="1" /> </VisualState.Setters> </VisualState> <VisualState x:Name="NarrowState"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="IngredientsPanel.(Grid.Row)" Value="1" /> <Setter Target="IngredientsPanel.(Grid.Column)" Value="0" /> <Setter Target="DirectionsPanel.(Grid.Row)" Value="2" /> <Setter Target="DirectionsPanel.(Grid.Column)" Value="0" /> <Setter Target="ImagePanel.(Grid.ColumnSpan)" Value="3" /> <Setter Target="IngredientsPanel.(Grid.ColumnSpan)" Value="3" /> <Setter Target="DirectionsPanel.(Grid.ColumnSpan)" Value="3" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> </Grid> </Page>
AdaptiveTrigger является единственным нововведенным триггером, включенным в Windows 10, но он предоставляется возможность с легкостью разрабатывать действительно гибкие интерфейсы пользователя, при всем этом еще и избавляясь от C# кода в странице.
Ссылка на источник: Using AdaptiveTrigger To Build Adaptive UIs In Windows 10
А подскажите, как использовать другие триггеры в UWP-приложениях? Состояния приложения бывают ведь разными, и надо отслеживать не только ширину экрана. Например, вместе с использованием AdaptiveTrigger MinWindowWidth мне ещё надо, чтобы один элемент был виден тогда, когда скрыт другой, и наоборот. Подробно вопрос изложил вот здесь: https://social.msdn.microsoft.com/Forums/en-US/b50bb40c-89ac-4199-9d38-fafbf4bac0a0/-uwp?forum=winstoreappsru
Отбой. Разобрался.