Элемент Slider в WinRT
113WinRT --- Элемент Slider
В приведенной ранее иерархии классов Control мы еще не рассмотрели важный класс RangeBase, у которого имеются три производных класса: ProgressBar, ScrollBar и Slider.
Какой из этих классов отличается от других? Конечно, класс ProgressBar, который существует в этой иерархии в основном для наследования нескольких свойств RangeBase - Minimum, Maximum, SmallChange, LargeChange и Value. В каждом элементе управления RangeBase свойство Value принимает значения типа double в диапазоне от Minimum до Maximum. В классах ScrollBar и Slider свойство Value изменяется, когда пользователь работает с элементом управления; в классе ProgressBar свойство Value задается на программном уровне для обозначения текущего состояния продолжительной операции. У класса ProgressBar также имеется недетерминированный режим, в котором по экрану «бежит» строка точек, но аналогичная функциональность также реализован в классе ProgressRing, отображающем хорошо знакомый круг из точек.
За четверть века эволюции Windows класс ScrollBar покинул свое высокое место в иерархии элементов управления. В наши дни он обычно встречается только в элементе ScrollViewer. Попробуйте создать экземпляр ScrollBar для Windows Runtime - вы его даже не увидите. Чтобы использовать элемент управления ScrollBar, необходимо предоставить для него шаблон. Как и класс RangeBase, класс ScrollBar определяется в пространстве имен Windows.UI.Xaml.Controls.Primitives, то есть этот класс не предназначен для повседневного использования при программировании приложений.
Практически для всех задач, связанных с выбором из диапазона вариантов, класс ScrollBar был заменен классом Slider, а с интерфейсами сенсорного ввода выполнять операции со Slider стало проще чем когда-либо. В своей стандартной реализации элемент управления Slider не содержит кнопок со стрелками - он просто переходит к значению, соответствующему точке касания или перетаскивания пальцем/мышью.
Значение Value элемента управления Slider может изменяться либо программным способом, либо в результате действий пользователя. Чтобы получить оповещение об изменении свойства Value, присоедините обработчик события ValueChanged, как показано в примере ниже:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Slider ValueChanged="Slider_ValueChanged" />
<TextBlock HorizontalAlignment="Center"
FontSize="48" />
<Slider ValueChanged="Slider_ValueChanged" />
<TextBlock HorizontalAlignment="Center"
FontSize="48" />
</StackPanel>
</Grid>
Оба элемента управления Slider в этом примере используют один обработчик события. Идея этой простой программы заключается в том, что текущее значение каждого элемента управления Slider выводится в элементе TextBlock, расположенном под ним. На первый взгляд задача кажется нетривиальной, особенно когда вы видите, что в разметке XAML имена ничему не присваиваются. Однако обработчик события предполагает, что родителем Slider является элемент Panel, а следующим потомком в Panel является TextBlock:
private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
Slider slider = sender as Slider;
Panel parent = slider.Parent as Panel;
int childIndex = parent.Children.IndexOf(slider);
TextBlock txb = parent.Children[childIndex + 1] as TextBlock;
txb.Text = e.NewValue.ToString();
}
Этот трюк всего лишь демонстрирует, что к элементам визуального дерева можно обращаться несколькими способами. На завершающем шаге свойству Text элемента TextBlock присваивается аргумент NewValue из аргументов события, преобразованы в строку. С таким же успехом можно использовать свойство Value элемента Slider:
txb.Text = slider.Value.ToString();
И хотя класс RangeBaseValueChangedEventArgs является производным от RoutedEvent, данное событие не является маршрутизируемым. Оно не перемещается вверх по визуальному дереву. Аргумент sender всегда содержит Slider, а свойство OriginalSource аргументов события всегда равно null.
Запустив программу, вы увидите, что элементы TextBlock изначально не содержат ничего. Событие ValueChanged не генерируется до того момента, как у Value изменится значение по умолчанию, равное нулю.
Если прикоснуться к шкале Slider или щелкнуть на ней мышью, значение переходит в выбранную позицию. Перемещая палец или указатель мыши вперед-назад, можно изменять значение. Экспериментируя с элементами управления Slider, вы увидите, что они позволяют выбирать значения из диапазона от 0 до 100 включительно.
Этот диапазон определяется значениями по умолчанию свойств Minimum и Maximum, равными 0 и 100 включительно. Свойство Value относится к типу double, оно получает целочисленные значения свойства StepFrequency, равного 1. По умолчанию элемент управления Slider ориентирован горизонтально, но вы можете переключиться на вертикальную ориентацию при помощи свойства Orientation. Толщину Slider невозможно изменить без переопределения визуального оформления в шаблоне. В шаблоне элемент занимает чуть больше места, чем кажется. В макете высота горизонтальной элемента управления Slider составляет 60 пикселов; ширина по умолчанию вертикального элемента управления Slider составляет 45 пикселов. Эти размеры хороша подходят для операций с сенсорным экраном.
Если нажать клавишу Tab во время выполнения этой программы, фокус ввода клавиатуры перейдет от одного элемента управления Slider к другому, а клавиши со стрелками позволяют увеличивать и уменьшать значение. Клавиши Home и End осуществляют переход к минимальному и максимальному значению шкалы соответственно.
В следующем примере вся логика обновления перемешена файл XAML. В StackPanel создаются экземпляры трех элементов Slider, которые чередуются с элементами TextBlock, привязанными к значениям свойств Value всех элементов Slider. Для сокращения дублирования разметки определяется неявный стиль для TextBlock:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="48" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Grid.Resources>
<StackPanel>
<Slider x:Name="slider1" />
<TextBlock Text="{Binding ElementName=slider1, Path=Value}" />
<Slider x:Name="slider2" IsDirectionReversed="True"
StepFrequency="0.01"/>
<TextBlock Text="{Binding ElementName=slider2, Path=Value}" />
<Slider x:Name="slider3"
Minimum="-1" Maximum="1"
SmallChange="0.01"
StepFrequency="0.01"
LargeChange="0.1"/>
<TextBlock Text="{Binding ElementName=slider3, Path=Value}" />
</StackPanel>
</Grid>
Привязки получают исходные значения и не дожидаются срабатывания первого события ValueChanged. Далее они отслеживают изменения значений, обусловленные действиями пользователя.
Разметка второго элемента управления Slider задает свойству StepFrequency значение 0.01, а свойство IsDirectionReversed задается равным true, чтобы правый край шкалы соответствовал минимальному значению 0. Для горизонтальных элементов Slider такое значение IsDirectionReversed используется редко, оно более распространено для вертикальной ориентации. По умолчанию у вертикального элемента управления Slider минимальное значение находится у нижней границы шкалы, но в некоторые ситуациях это положение должно соответствовать максимальному значению.
У второго элемента управления Slider клавиши со стрелками изменяют значение с приращением 1 (вместо значения StepFrequency, равного 0.01). Клавиатурным интерфейсом управляет свойство SmallChange, по умолчанию равное 1.
Третий элемент управления Slider использует диапазон от -1 до 1. При исходном отображении Slider ползунок располагается в центре со значением по умолчанию 0. Я задал свойствам StepFrequency и SmallChange значения 0.01, а свойству LargeChange значение 0.1, но не нашел способа инициировать переход LargeChange с мыши или клавиатуры.
Класс Slider определяет свойства TickFrequency и TickPlacement для отображения засечек рядом со шкалой. Если у элемента управления Slider заданы свойства Background и Foreground, он использует Foreground для области, связанной с минимальным значением, и Background для области, связанной с максимальным значением, но переключается на цвета по умолчанию при выполнении действий пользователя или наведении указателя мыши.
По мере того как на странице появляется больше элементов управления Slider, возникает необходимость в более совершенных средствах их размещения. Пора поближе познакомиться с элементом Grid.