Главная » Разработка для Windows Phone 7 » Выбор в ListBox

0

Selector (класс, от которого наследуются ListBox и ComboBox) определяет свойство SelectedIndex (Индекс выбранного элемента), значением которого является индекс выбранного элемента или -1, если в данный момент не выбран ни один элемент. В Selector также описывается свойство SelectedItem (Выбранный элемент), значением которого является выбранный элемент или null, если ни один элемент не выбран. Если SelectedIndex не равен -1, значением SelectedItem является тот же объект, что возвращает свойство Items при передаче в него SelectedIndex.

Событие SelectionChanged формируется при выборе другого элемента. Это событие подразумевает, что SelectedItem замечательно подходит для использования в качестве источника привязки. SelectedItem дублируется свойством-зависимостью, так что он также может быть целью привязки.

Если свойства SelectedIndex или SelectedItem объекта ListBox не заданы явно, и пользователь еще не касался ListBox, SelectedIndex будет равен -1, и SelectedItem будет иметь значение null. Не лишним будет подготовиться к таким ситуациям.

Приложение ListBoxSelection (Выбор элемента в окне списка) позволяет пользователю выбирать Color и FontFamily из двух элементов управления ListBox и выводить на экран некоторый текст на основании сделанного выбора. Коллекция Resources включает стандартный конвертер привязок и Style для ListBox:

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

<phone:PhoneApplicationPage.Resources>

<petzold:StringFormatConverter x:Name="stringFormat" />

<Style x:Key="listBoxStyle" TargetType="ListBox"> <Setter Property="BorderBrush"

Value="{StaticResource PhoneForegroundBrush}" /> <Setter Property="BorderThickness"

Value="{StaticResource PhoneBorderThickness}" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="Margin" Value="3" /> <Setter Property="Padding" Value="3" /> </Style>

</phone:PhoneApplicationPage.Resources>

Все три элемента располагаются в Grid с тремя строками: Проект Silverlight: ListBoxSelection Файл: MainPage.xaml (фрагмент)

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

<RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions>

</Grid>

ListBox включает список объектов SolidColorBrush с тем же шаблоном DataTemplate, что использовался в предыдущем приложении для форматирования элементов:

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

<ListBox Name="brushListBox" Grid.Row="0" SelectedIndex="0"

Style="{StaticResource listBoxStyle}"> <ListBox.ItemTemplate> <DataTemplate>

<StackPanel 0rientation="Horizontal"> <Rectangle Width="48" Height="36" Margin="2" Fill="{Binding}" />

<StackPanel 0rientation="Horizontal"

VerticalAlignment="Center"> <TextBlock Text="{Binding Color.R,

Converter={StaticResource stringFormat}, ConverterParameter=’ {0:X2}’}" /> <TextBlock Text="{Binding Color.G,

Converter={StaticResource stringFormat}, ConverterParameter=’-{0:X2}’}" /> <TextBlock Text="{Binding Color.B,

Converter={StaticResource stringFormat}, ConverterParameter=’-{0:X2}’}" />

</StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate>

<SolidColorBrush Color="AliceBlue" /> <SolidColorBrush Color="AntiqueWhite" /> <SolidColorBrush Color="Aqua" /> <SolidColorBrush Color="Aquamarine" /> <SolidColorBrush Color="Azure" />

<SolidColorBrush Color="Wheat" /> <SolidColorBrush Color="White" /> <SolidColorBrush Color="WhiteSmoke" /> <SolidColorBrush Color="Yellow" /> <SolidColorBrush Color="YellowGreen" /> </ListBox>

Обратите внимание, что SelectedIndex явно задано значение 0. Благодаря этому ListBox будет иметь действительный SelectedItem при запуске приложения.

Во втором ListBox отображаются семейства шрифтов. Я бы предпочел использовать реальные объекты FontFamily, но они не могут быть созданы в XAML, потому что у FontFamily нет конструктора без параметров. Поэтому мне пришлось сохранять имена в виде строк. Начальным значением SelectedIndex задано 5, я выбрал это число произвольно.

Было бы вполне логичным, если бы имена семейств шрифтов в ListBox выводились шрифтом, который они обозначают? Это легко реализовать с помощью DataTemplate. Просто с помощью привязки свяжем свойства Text и FontFamily объекта TextBlock с элементами ListBox:

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

<ListBox Name="fontFamilyListBox" Grid.Row="1" SelectedIndex="5"

Style="{StaticResource listBoxStyle}"> <ListBox.ItemTemplate> <DataTemplate>

<TextBlock Text="{Binding}"

FontFamily="{Binding}" />

</DataTemplate> </ListBox.ItemTemplate>

<system:String>Arial</system:String> <system:String>Arial Black</system:String> <system:String>Calibri</system:String> <system:String>Comic Sans MS</system:String> <system:String>Courier New</system:String> <system:String>Georgia</system:String> <system:String>Lucida Sans Unicode</system:String> <system:String>Portable User Interface</system:String> <system:String>Segoe WP</system:String> <system:String>Segoe WP Black</system:String> <system:String>Segoe WP Bold</system:String>

<system:String>Segoe WP Light</system:String> <system:String>Segoe WP Semibold</system:String> <system:String>Segoe WP SemiLight</system:String> <system:String>Tahoma</system:String> <system:String>Times New Roman</system:String> <system:String>Trebuchet MS</system:String> <system:String>Verdana</system:String> <system:String>Webdings</system:String> </ListBox>

Поскольку элементы в ListBox являются строками, а не объектами FontFamily, я не был уверен, что привязка к FontFamily в шаблоне будет работать, но все получилось.

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

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

<TextBlock Grid.Row="2"

Text="Sample Text"

FontSize="{StaticResource PhoneFontSizeExtraLarge}"

HorizontalAlignment="Center"

Margin="12"

Foreground="{Binding ElementName=brushListBox, Path=SelectedItem}"

FontFamily="{Binding ElementName=fontFamilyListBox, Path=SelectedItem}" />

Когда я впервые создал это приложение, казалось, что привязка FontFamily в DataTemplate работала нормально, а вот привязка FontFamily в конце описания TextBlock приводила к исключению времени выполнения. Я написал StringToFontFamilyConverter (Конвертер строки в семейство шрифтов) (который до сих пор можно найти в библиотеке Petzold.Phone.Silverlight), но, казалось, проблема касалась значения null для SelectedItem из ListBox. Избавиться от этой проблемы с привязкой помогло явное задание начального SelectedIndex.

Если немного поиграть с этим приложением, можно заметить, что TextBlock немного меняет высоту при изменении FontFamily. Это создает эффект домино, приводя к изменениям высот двух ListBox. ListBox также может менять ширину. Если HorizontalAlignment не Stretch, ширина ListBox будет как раз такой, какая необходима для отображения содержимого. Но поскольку ListBox по умолчанию использует VirtualizingStackPanel, деревья визуальных элементов для элементов списка создаются только тогда, когда они должны отображаться. Таким образом, ListBox не всегда знает ширину своего самого широкого элемента. Очень странно видеть изменение ширины ListBox при прокрутке списка элементов!

По этим причинам ширину и высоту ListBox часто задают явно или посредством Grid.

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

По теме:

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