В прошлой теме была рассмотрена адаптация элементов управления к изменениям ширины экрана на основе обработки события SizeChanged. Но Universal Windows Platform также предоставляет и другое более эффективное решение - Visual States или визуальные состояния.
Элементы визуальных состояний используются для представления внешнего вида элементов интерфейса, когда они находятся в каком-то определенном состоянии. Для управления визуальными состояниями применяется объект VisualStateManager. Для примера возьмем код приложения из прошлой темы и применим к нему визуальные состояния:
<Page x:Class="AdaptiveApp.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:AdaptiveApp" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <Style TargetType="Button" x:Key="horizontalButtonStyle"> <Setter Property="Width" Value="80" /> <Setter Property="Background" Value="LightPink" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="Margin" Value="10" /> </Style> <Style TargetType="Button" x:Key="verticalButtonStyle"> <Setter Property="Width" Value="100" /> <Setter Property="Background" Value="LightBlue" /> <Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="Margin" Value="15" /> </Style> </Page.Resources> <StackPanel Name="buttonStack" Orientation="Horizontal" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState x:Name="Desktop"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="500" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="buttonStack.Orientation" Value="Horizontal" /> <Setter Target="button1.Style" Value="{StaticResource horizontalButtonStyle}" /> <Setter Target="button2.Style" Value="{StaticResource horizontalButtonStyle}" /> <Setter Target="button3.Style" Value="{StaticResource horizontalButtonStyle}" /> <Setter Target="button4.Style" Value="{StaticResource horizontalButtonStyle}" /> </VisualState.Setters> </VisualState> <VisualState x:Name="Mobile"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <Setter Target="buttonStack.Orientation" Value="Vertical" /> <Setter Target="button1.Style" Value="{StaticResource verticalButtonStyle}" /> <Setter Target="button2.Style" Value="{StaticResource verticalButtonStyle}" /> <Setter Target="button3.Style" Value="{StaticResource verticalButtonStyle}" /> <Setter Target="button4.Style" Value="{StaticResource verticalButtonStyle}" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Button Name="button1" Content="button 1" /> <Button Name="button2" Content="button 2" /> <Button Name="button3" Content="button 3" /> <Button Name="button4" Content="button 4" /> </StackPanel> </Page>
Все визуальные состояния определяются в корневом элементе компоновки, в данном случае в StackPanel. Для определения визуальных состояний используется свойство VisualStateManager.VisualStateGroups. В него помещается элемент VisualStateGroup, который представляет набор состояний. Каждое визуальное состояние задается с помощью объекта VisualState. Он имеет имя. В данном случае у нас два состояния: Mobile и Desktop.
Для каждого состояния определяется набор адаптивных триггеров с помощью коллекции VisualState.StateTriggers и объектов AdaptiveTrigger. Адаптивные триггеры задают условие, при достижении которого приложение переходит в данное визуальное состояние. По большому счету мы можем задать только два условия - минимальную ширину окна приложения через свойство MinWindowWidth и и минимальную высоту окна с помощью свойства MinWindowHeight.
В данном случае приложение попадает в первое визуальное состояние Desktop, когда ширина окна от 500 единиц и больше, а во второе состояние - когда ширина окна больше 0.
И также каждый объект VisualState содержит коллекцию VisualState.Setters. Каждый объект Setter в этой коллекции устанавливает значение для какого-то
определенного свойства элемента. Само свойство указывается через атрибут Target, например, Target="buttonStack.Orientation"
. Для ссылки на элемент используется
его имя buttonStack.
Теперь в файле кода MainPage.xaml.cs нам не надо устанавливать обработчик события SizeChanged или писать какую-то другую логику. Все будет делаться автоматически при изменении размеров окна приложения.