Главная » Разработка для Windows Phone 7 » Два примера использования ScrollViewer

0

Если StackPanel включает больше элементов, чем помещается на экране (или любом другом контейнере, в котором располагается StackPanel), самые нижние (или правые) элементы будут не видны.

Если есть опасение, что все дочерние элементы StackPanel не поместятся на экране телефона, StackPanel можно поместить в ScrollViewer (Прокручиваемая область). ScrollViewer – это элемент управления, определяющий необходимые размеры для отображения своего содержимого и предоставляющий одну или две полосы прокрутки.

В Windows Phone 7 полосы прокрутки, скорее, виртуальные, чем реальные. Мы прокручиваем ScrollViewer не с помощью полос прокрутки, а просто перемещаем страницу, проводя пальцем по экрану. Но при обсуждении этой функциональности удобно использовать традиционное понятие полосы прокрутки, поэтому я буду его придерживаться.

По умолчанию вертикальная полоса прокрутки видима, и горизонтальная скрыта, но это поведение можно переопределить с помощью свойств VerticalScrollBarVisibility (Видимость вертикальной полосы прокрутки) и HorizontalScrollBarVisibility (Видимость горизонтальной полосы прокрутки). Возможные значения этих свойств являются членами перечисления ScrollBarVisibility (Видимость полосы прокрутки): Visible, Hidden (Скрыта), Auto (видима только в случае необходимости) и Disabled (Отключена) (видима, но не активна).

Следующее приложение-пример является средством для чтения электронных книг. Ну, скажем, не вполне книг, скорее, отрывков из книг. Также это приложение не отличается универсальностью, оно отображает лишь небольшую юмористическую заметку, написанную Марком Твеном в 1880 году, которая считается первым описанием впечатлений человека, ставшего свидетелем разговора по телефону, без возможности слышать второго собеседника. (Женщина, говорящая по телефону – жена Марка Твена, Оливия.)

Я внес небольшие дополнения в заголовок: выделил его другим цветом и разбил на две строки:

Проект Silverlight: TelephonicConversation Файл: MainPage.xaml (фрагмент)

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="2 4,2 4,0,12"> <TextBlock x:Name="ApplicationTitle"

Style="{StaticResource PhoneTextNormalStyle}" TextAlignment="Center"

Foreground="{StaticResource PhoneAccentBrush}"> "A Telephonic Conversation"<LineBreak />by Mark Twain

</TextBlock> </ StackPanel>

Сетка для содержимого включает собственную коллекцию Resources с заданным Style. В Grid расположен ScrollViewer, в котором находится StackPanel, включающий два элемента TextBlock с рассказом, по одному для каждого абзаца. Обратите внимание на четкое разделение задач: элементы TextBlock отображают текст, StackPanel обеспечивает компоновку, ScrollViewer обеспечивает прокрутку:

Проект Silverlight: TelephonicConversation Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.Resources>

<Style x:Key="paragraphStyle" TargetType="TextBlock">

<Setter Property="TextWrapping" Value="Wrap" />

<Setter Property="Margin" Value="5" />

<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeSmall}"

/>

</Style> </Grid.Resources>

<ScrollViewer Padding="5"> <StackPanel>

<TextBlock Style="{StaticResource paragraphStyle}">

&#x2003;I consider that a conversation by telephone — when you are simply sitting by and not taking any part in that conversation — is one of the solemnest curiosities of this modern life. Yesterday I was writing a deep article on a sublime philosophical subject while such a conversation was going on in the room. I notice that one can always write best when somebody is talking through a telephone close by. Well, the thing began in this way. A member of our household came in and asked me to have our house put into communication with Mr. Bagley’s, down town. I have observed, in many cities, that the sex always shrink from calling up the central office themselves. I don’t know why, but they do. So I touched the bell, and this talk ensued: —

</TextBlock>

<TextBlock Style="{StaticResource paragraphStyle}">

&#x2 0 03;<Run FontStyle="Italic">Central Office.</Run> [Gruffly.] Hello!

</TextBlock>

<TextBlock Style="{StaticResource paragraphStyle}">

&#x2 0 03;<Run FontStyle="Italic">I.</Run> Is it the Central Office?

</TextBlock>

<TextBlock Style="{StaticResource paragraphStyle}" TextAlignment="Right"> — <Run FontStyle="Italic">Atlantic Monthly</Run>, June 1880

</TextBlock> </StackPanel> </ScrollViewer> </Grid>

Конечно же, это не весь файл. Большую часть рассказа я заменил здесь на многоточия (…).

Чтобы StackPanel не прилегал вплотную к краям, для ScrollViewer задан отступ (Padding) в 5 пикселов. Кроме того, свойству Margin каждого TextBlock задано значение 5 пикселов посредством Style. Отступ и поле дают в сумме по 10 пикселов справа и слева и 10 пикселов

между каждым TextBlock, что делает абзацы более различимыми и текст более удобным для восприятия.

Также я вставил Unicode-символ &#x2003; в начало каждого абзаца. Это длинный пробел в кодировке Unicode, который эффективно обеспечивает отступ первой строки на ширину одного символа.

По умолчанию ScrollViewer обеспечивает вертикальную прокрутку. Элемент управления реагирует на касание, что позволяет без труда «прокручивать» отображаемый текст и прочитать рассказ полностью.

В приложении PublicClasses (Открытые классы), которое мы рассмотрим следующим, также есть ScrollViewer, включающий вертикальный StackPanel, но заполнение этой панели реализовано полностью в коде. Используя технологию отражения, файл выделенного кода получает все открытые классы, предоставляемые сборками System.Windows, Microsoft.Phone, Microsoft.Phone.Controls и Microsoft.Phone.Controls.Maps, и представляет их список в виде иерархии классов.

Для обеспечения этого в XAML-файл включен пустой StackPanel, идентифицируемый по имени:

Проект Silverlight: PublicClasses Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ScrollViewer HorizontalScrollBarVisibility="Auto">

<StackPanel Naшe="stackPanelм /> </ScrollViewer> </Grid>

По умолчанию VerticalScrollBarVisibility имеет значение Visible, и я задал для свойства HorizontalScrollBarVisibility значение Auto. Если какая-либо строка текста будет слишком длинной и не поместится на экране, ее можно будет увидеть посредством горизонтальной прокрутки.

Данная горизонтальная прокрутка существенно отличает данное приложение от предыдущего. Когда текст автоматически переносится на новую строку, как это было в проекте TelephonicConversation (Разговор по телефону), в горизонтальной прокрутке нет необходимости. В данном приложении длина строк без переносов может превышать ширину экрана, поэтому желательно предусмотреть горизонтальную полосу прокрутки.

Файл выделенного кода использует отдельный небольшой класс ClassAndChildren (Класс и потомки) для хранения иерархии классов, представляемой в виде дерева.

Проект Silverlight: PublicClasses Файл: ClassAndChildren.cs

using System;

using System.Collections.Generic;

namespace PublicClasses {

class ClassAndChildren {

public ClassAndChildren(Type parent) {

Type = parent;

SubClasses = new List<ClassAndChildren>();

}

public Type Type { set; get; }

public List<ClassAndChildren> SubClasses { set; get; }

}

}

Объект ClassAndChildren создается для каждого класса, отображаемого в дереве. Каждый объект ClassAndChildren включает объект List (Список) со всеми классами, наследуемыми от данного.

Привожу код класса MainPage полностью. Ему необходима директива using для подключения пространства имен System.Reflection.

Проект Silverlight: PublicClasses Файл: MainPage.xaml.cs (фрагмент)

public partial class MainPage : PhoneApplicationPage {

Brush accentBrush;

public MainPage() {

InitializeComponent();

accentBrush = this.Resources["PhoneAccentBrush"] as Brush; // Загружаем все сборки

List<Assembly> assemblies = new List<Assembly>(); assemblies.Add(Assembly.Load("System.Windows")); assemblies.Add(Assembly.Load("Microsoft.Phone")); assemblies.Add(Assembly.Load("Microsoft.Phone.Controls")); assemblies.Add(Assembly.Load("Microsoft.Phone.Controls.Maps"));

// Задаем корневой объект (используем DependencyObject, // чтобы сделать список короче) Type typeRoot = typeof(object);

// Составляем полный список открытых классов List<Type> classes = new List<Type>(); classes.Add(typeRoot);

foreach (Assembly assembly in assemblies)

foreach (Type type in assembly.GetTypes())

if (type.IsPublic && type.IsSubclass0f(typeRoot)) classes.Add(type);

// Сортируем эти классы classes.Sort(TypeCompare);

// Теперь помещаем все эти сортированные классы в древовидную структуру ClassAndChildren rootClass = new ClassAndChildren(typeRoot); AddToTree(rootClass, classes);

// Выводим дерево на экран Display(rootClass, 0);

}

int TypeCompare(Type t1, Type t2) {

return String.Compare(t1.Name, t2.Name);

}

// Рекурсивный метод

void AddToTree(ClassAndChildren parentClass, List<Type> classes) {

foreach (Type type in classes) {

if (type.BaseType == parentClass.Type) {

ClassAndChildren subClass = new ClassAndChildren(type); parentClass.SubClasses.Add(subClass); AddToTree(subClass, classes);

}

}

}

// Рекурсивный метод

void Display(ClassAndChildren parentClass, int indent) {

string str1 = String.Format("{0}{1}{2}{3}",

new string(‘ ‘, indent * 4), parentClass.Type.Name,

parentClass.Type.IsAbstract ? " (abstract)" :

parentClass.Type.IsSealed ? " (sealed)" : "");

string str2 = " " + parentClass.Type.Namespace;

TextBlock txtblk = new TextBlock(); txtblk.Inlines.Add(str1);

txtblk.Inlines.Add(new Run {

Text = str2,

Foreground = accentBrush

});

stackPanel.Children.Add(txtblk);

foreach (ClassAndChildren child in parentClass.SubClasses) Display(child, indent + 1);

}

Конструктор сначала сохраняет все открытые классы из основных сборок Silverlight в большую коллекцию. После этого они сортируются по имени и распределяются в объекты ClassAndChildren с помощью рекурсивного метода. Второй рекурсивный метод добавляет элементы TextBlock в StackPanel. Обратите внимание, что каждый элемент TextBlock включает

коллекцию Inlines с двумя объектами Run. Для улучшения восприятия я решил выделить имена пространств имен другим цветом и для удобства использовал контрастный цвет, выбранный пользователем.

На рисунке показана часть иерархии классов, представляющая класс Panel и производные от него классы:

Источник: Чарльз Петзольд, Программируем Windows Phone 7, Microsoft Press, © 2011.

По теме:

  • Комментарии