Как известно, в CTP версии Windows Phone 7 Developer kit не поддерживаются некоторые элементы управления: ComboBox, Frame, многие элементы управления из Silverlight Toolkit. Таким образом, при необходимости использовать какие-либо из этих контролов возникает задача написания собственной версии специально для Windows Phone 7.
Идея
Именно такая задача встала передо мной. В этом посте я расскажу, как именно я ее решил. Сразу предупреждаю - это отнюдь не финальная реализация, это скорее небольшой набросок, иллюстрация. Для ее завершения, как минимум, необходимо добавить стили, соответствующие системным и исправить некоторые мелкие проблемы.
Идея заключается в следующем: разместим в элементе управления TextBlock, содержащий выбранный элемент, и ListBox, содержащий список элементов. Высоту TextBlock'а сделаем примерно в 64 пикселя, высоту списка же -в несколько раз больше. В зависимости от того, в каком состоянии находится элемент управления, будем изменять высоту элемента в соответствии с высотой отображаемого содержимого.
Всего допустимы 2 состояния:
1. Свернутое состояние - высота минимальна, отображается только TextBlock.
2. Развернутое состояние - высота максимальна, отображается только ListBox.
Реализация
Прежде всего добавим в проект новый UserControl и наберем примерно такую разметку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<!-- Внешняя граница контрола --> <Border BorderBrush="{StaticResource PhoneForegroundBrush}" BorderThickness="{StaticResource PhoneDefaultBorderThickness}" Background="{StaticResource TransparentBrush}"> <!-- Контейнер для содержимого контрола. Размер этого контейнера будет изменяться в зависимости от того, в каком состоянии находится контрол --> <Grid x:Name="LayoutRoot" Background="{StaticResource TransparentBrush}" Height="64"> <Grid.Resources> <!-- Здесь будут размещены анимации свертывания и развертывания списка --> </Grid.Resources> <Border VerticalAlignment="Center"> <!-- Здесь отображается текущий выбранный элемент --> <TextBlock x:Name="SelectedValueTextBlock" Style="{StaticResource PhoneTextLargeStyle}" VerticalAlignment="Center" MouseLeftButtonDown="SelectedValueTextMouseLeftButtonDown" TextWrapping="Wrap" Margin="20,12,20,12" /> </Border> <!-- Собственно выпадающий список --> <ListBox x:Name="DropDownList" VerticalAlignment="Top" MinHeight="250" SelectionMode="Single" SelectionChanged="DropDownList_SelectionChanged" Visibility="Collapsed" Padding="0"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <StackPanel /> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Style="{StaticResource PhoneTextLargeStyle}" Margin="15,0,15,0" TextWrapping="Wrap" Text="{Binding}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Border> |
Следующее, что необходимо набрать – код анимации для развертывания и свертывания списка. Я реализовал весьма простую анимацию:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<Storyboard x:Name="ExpandListStoryboard"> <DoubleAnimation Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Height" From="64" To="250" Duration="0:00:00.25"> <DoubleAnimation.EasingFunction> <PowerEase EasingMode="EaseIn" /> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard> <Storyboard x:Name="CollapseListStoryboard" Completed="CollapseListStoryboard_Completed"> <DoubleAnimation Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Height" From="250" To="64" Duration="0:00:00.25"> <DoubleAnimation.EasingFunction> <PowerEase EasingMode="EaseOut" /> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard> |
Теперь осталось написать C#-код для обработки событий:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace ComboBoxExample { public partial class ComboBox : UserControl { public ComboBox() { InitializeComponent(); } /// <summary> /// Значение true соответствует развернутому состоянию выпадающего списка /// </summary> public bool IsExpanded { get { return isExpanded; } set { // при переключении состояния переключается свойство Visibility у выпадающего списка и у TextBlock'а SelectedValueTextBlock.Visibility = !value ? Visibility.Visible : Visibility.Collapsed; DropDownList.Visibility = value ? Visibility.Visible : Visibility.Collapsed; isExpanded = value; } } /// <summary> /// Элементы списка /// </summary> public IEnumerable Items { get { return (IEnumerable)DropDownList.ItemsSource; } set { DropDownList.ItemsSource = value; // автоматически выбираем первый элемент SelectedItem = value.Cast<object>().First(); } } /// <summary> /// Выбранный элемент списка /// </summary> public object SelectedItem { get { return selectedItem; } set { selectedItem = value; // задаем текст для TextBlock'а, представляющего выбранный элемент SelectedValueTextBlock.Text = value.ToString(); } } private bool isExpanded; private object selectedItem; private void OnLoaded(object sender, RoutedEventArgs e) { // задание начального состояния - список свернут IsExpanded = false; } /// <summary> /// Разворчивает список /// </summary> private void ExpandList() { // переключение состояния IsExpanded = true; // Запуск анимации ExpandListStoryboard.Begin(); } /// <summary> /// Свертывает список /// </summary> private void CollapseList() { // запуск анимации сворачивания CollapseListStoryboard.Begin(); } private void SelectedValueTextMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // при клике по TextBlock'у, представляющего выбранный элемент, список разворачивается ExpandList(); } private void CollapseListStoryboard_Completed(object sender, EventArgs e) { // по завершении анимации сворачивания списка - переключаем состояние IsExpanded = false; } private void DropDownList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) { // при выборе элемента из списка - устанавливаем выбранный элемент и сворачиваем список SelectedItem = DropDownList.SelectedItem; CollapseList(); } } } |
Результат
Недоработки
1. Стилизация - данная реализация выпадающего списка не поддерживает стили, не позволяет гибко переопределять визуальное представление элементов.
2. Гибкость - в данной реализации нет возможности настраивать высоту выпадающего списка.
3. Шаблонизация - в данной реализации нет поддержки шаблонов для элементов списка.
4. Визуальные эффекты - в отличие от системного ComboBox'а Windows Phone 7 эффект прокрутки при выборе элемента списка отсутствует.
Спасибо за внимание!
Надеюсь, эта короткая статья поможет в разработке ПО для Windows Phone 7.
Круто. Надо будет тоже попробовать для windows phone что-нибудь сделать
Что-то не пашет System.AccessViolationException
Разумеется, не работает, написано же "в CTP версии Windows Phone 7 Developer kit".
http://phone.codeplex.com/ поможет тебе, если нужен комбобокс для wp7/8.
Ну не ра бо та ет ттттттт