Pull to refresh

TextBox с печеньками при помощи User Control, Windows Phone/Store

Reading time 4 min
Views 22K

Здравствуйте, уважаемые хаброжители!

Сегодня мы попробуем создать свой собственный TextBox с дополнительными удобствами.

Сразу скажу, что их будет только два:
Placeholder, также известный, как «текст по умолчанию»;
Clear Button — очень удобная в мире планшетов вещь, позволяющая быстро очистить содержимое нашего текстового поля.

Для туториала приведён пример Windows Phone-приложения, но держу пари, что оно же будет работать и с WPF, и с Silverlight. В Windows Store-приложениях есть кнопка очищения по умолчанию, но Placeholder добавляется так же.

Сразу хочу выразить благодарность @Useless_guy за отличную наводку в виде библиотеки компонентов The Windows Phone Toolkit.
Также, советую обратить внимание на библиотеку Coding4Fun.
Действительно, если нет особой надобности создавать свои UserControls — следует использовать готовые работающие решения.

Итак, приступим!

Вступление


Не секрет, что XAML является мощнейшим инструментом для создания интерфейса пользователя.

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

Но на самом деле, как только начинаешь понимать, собирая информацию по крупицам, о чём же думают ведущие разработчики Microsoft — всё становится намного понятнее, и ты уже не можешь понять, как ты до этого сам не додумался, ведь это очевидно…

Но от лирики пора перейти к практике.

Рубимся


Итак, первое что нам понадобится — новый проект и новый User Control в нём.

1. Запускаем Visual Studio.

2. Создаём новый пустой проект под именем «AdvancedTextBoxProject».

3. После создания проекта перейдём в Solution Explorer и нажмём на имени проекта правой кнопкой, а в контекстном меню выберем Add->New Item…

4. В диалоговом окне Add New Item выбираем User Control, обзываем его «AdvancedTextBox» и нажимаем кнопку «Add».

Теперь у нас есть наш новый компонент и мы можем начать создавать его дизайн.
Сейчас в XAML-коде нашего компонента нет ни единой строчки кроме пустого объявления элемента Grid, поэтому добавим в него (в Grid) то, что нам нужно — а именно, TextBox, который как раз и будет содержать в себе текст по умолчанию и кнопку очищения.

<StackPanel>
	<Grid>
		<TextBox x:Name="tbMain"></TextBox>
		<Button x:Name="bClear" HorizontalAlignment="Right" BorderThickness="0" Content="&#xE10A;" FontFamily="Segoe UI Symbol" Foreground="{StaticResource ApplicationPageBackgroundThemeBrush}" Visibility="Collapsed"></Button>
	</Grid>
</StackPanel>


Начнём по порядку — компонент StackPanel необходим для выравнивания контента внутри него построчно, иначе наш Grid растянулся бы на всю область компонента. Внутри него мы создаём Grid уже непосредственно связанный с представлением нашего компонента.

С компонентом TextBox мы не будем ничего делать, поэтому кидаем его на сцену и называем любым удобным именем, чтобы иметь возможность получить к нему доступ из кода нашего компонента.

А вот компонент Button необходимо подвергнуть пластической хирургии. Мы тоже дадим ему удобное имя, но, кроме этого скажем ему:
1. Чтобы он выравнивался по правому краю нашего компонента (HorizontalAlignment).
2. Чтобы у него не было ненужной нам границы компонента (BorderThickness).
3. Чтобы на кнопке был нарисован тот самый крестик (Content и FontFamily).
4. Чтобы крестик был цвета нашей основной темы Windows-устройства (Foreground).
5. И, наконец, чтобы в самом начале кнопки очищения не было видно (Visibility).

Напомню, что пункт 3 получился из комбинации вот этой картинки и файла StandardStyles.xaml (файл стилей из Windows Store-приложения).

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

Для начала мы организуем правильную обработку Placeholder, а уж потом самое простое — кнопку очищения.

Выбираем наш TextBox, в окне Properties выбираем Events и нажимаем дважды на событии GotFocus.

Так как мы ещё не написали ничего полезного, то в коде у нас есть только описание нашего класса, его конструктор с вызовом единственного метода InitializeComponent() и только что созданный нами обработчик события GotFocus().

Так как у нас в компоненте ещё нет поля, которое будет отвечать за Placeholder, то в первую очередь необходимо его создать:

private string placeholder="";

public string Placeholder
{
	get
	{
		return this.placeholder;
	}
	set
	{
		this.placeholder = value;
		tbMain.Text = this.placeholder;
	}
}


Ну, а теперь можно вернуться к описанию обработчика события GotFocus():

if (tbMain.Text.Trim() == this.placeholder)
{
	tbMain.Text = "";
}
bClear.Visibility = System.Windows.Visibility.Visible;


Здесь мы проверяем обрезанную (Trim()) строку нашего TextBox, — не текст ли по умолчанию там содержится? Если да, то очищаем поле и позволяем пользователю вводить всё, что ему угодно. Ну и заодно показываем ему кнопку очищения текстового поля.

Дальше нам нужно обработать событие, когда пользователь переключается из поля ввода куда-то в другое место, для этого мы снова открываем дизайн нашего компонента, выбираем TextBox и создаём обработчик события LostFocus(), в котором всё то же самое, но наоборот:

if (tbMain.Text.Trim() == "")
{
	tbMain.Text = this.placeholder;
}
bClear.Visibility = System.Windows.Visibility.Collapsed;


Теперь нам необходимо обработать событие Click кнопки очищения и можно уже тестировать наш новый компонент!

Для этого перейдём в дизайнер, но так как кнопка у нас спрятана от посторонних (и от наших впрочем тоже) глаз, то надо перейти в код XAML, нажать на объявление нашей кнопки и в окне Properties появятся события нашей кнопки. Выбираем Click и пишем в обработчике:

tbMain.Text = string.Empty;
tbMain.Focus();


В обработчике события щелчка по кнопке мы очищаем наш TextBox и возвращаем ему фокус. Нужно это потому, что при нажатии на кнопку автоматически срабатывает событие LostFocus нашего TextBox'а, и поэтому нам необходимо вернуть фокусировку обратно.

Тестируем



Ну что ж, теперь можно и протестировать всё то, что мы с таким неимоверным трудом понаписали.

Переходим в дизайнер главной страницы нашего приложения и добавляем в XAML-объявление Page ещё один Namespace:

xmlns:local="using:AdvancedTextBoxProject"


После проделанного, мы наконец-то можем добавить наш компонент на форму:

<local:AdvancedTextBox Placeholder="Enter Some Text"></local:AdvancedTextBox>


На форме в поле ввода сразу же появится наш текст по умолчанию и мы можем запустить наше приложение и посмотреть как это работает.

Кстати, для того, чтобы иметь возможность изменять поля вложенных компонентов через наш UserControl, надо всего лишь добавить public-поле с нужными нам геттером и сеттером, например:

public string Text
{
    get { return tbMain.Text; }
    set { tbMain.Text = value; }
}


Желаю удачи всем и до новых встреч!
Only registered users can participate in poll. Log in, please.
Была ли вам интересна данная статья?
64.06% Да 139
15.67% Нет 34
20.28% Пшёл вон, холоп! 44
217 users voted. 60 users abstained.
Only registered users can participate in poll. Log in, please.
Вы профессионал C#/XAML?
25.65% Ещё какой 69
55.39% Не сказал бы 149
18.96% Ваш сишарп сосёт у моего сиплюсплюса, неудачники 51
269 users voted. 61 users abstained.
Tags:
Hubs:
+4
Comments 8
Comments Comments 8

Articles