Под катом, будем пошаговое руководство, по разработке такого компонента, ориентированное на тех, кто первый раз подходит к разработке своих элементов управления. Для тех, кто уже программирует под Windows Store откровений не будет, но если не сложно, выложите рекомендации в комментариях, может кто-то действительно решит сделать хороший элемент управления для такой задачки.
Поехали.
Создаем новое Windows Store приложение. В Solution добавляем новую сборку (правый клик мыши на Solution, в контекстном меню Add -> New Project):
В эту сборку добавляем новый элемент (правый клик на проекте, Add -> New Item):
В файле cs нашего контрола, меняем предка на TextBox:
public sealed partial class WaterMarkedTextBox : TextBox
Также, нам придется поменять разметку, заменив базовый компонент и удалив содержимое:
Эти нехитрые действия, позволили нам получить в своем компоненте все поля и методы, которые были у базового TextBox-а. Единственно, что нас не устраивает, это отсутствие у TextBox-а возможности показывать подсказку. Переопределим шаблон нашего потомка TextBox-а, добавив в него TextBlock, для отображения подсказки:
<TextBox.Template> <ControlTemplate TargetType="TextBox"> <Grid> <TextBox Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}" /> <TextBlock Text="{Binding WaterMark, RelativeSource={RelativeSource TemplatedParent}}" Foreground="Gray" Margin="5,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Visibility="Collapsed" IsHitTestVisible="False"/> </Grid> </ControlTemplate> </TextBox.Template>
Т.к. в конструкторе работать с визуальными компонентами еще нельзя, то подпишемся на событие загрузки компонента и всю полезную работу будем выполнять в обработчике этого события:
public WaterMarkedTextBox() { this.InitializeComponent(); Loaded += WaterMarkedTextBox_Loaded; }
Для определения, есть у нас фокус на элементе или нет, добавим поле:
private bool _isFocused;
Ну и нам понадобиться DependencyProperty, для хранения текста подсказки:
/// <summary> /// Подсказка показываемая пользователю /// </summary> public string WaterMark { get { return (string)GetValue(WaterMarkProperty); } set { SetValue(WaterMarkProperty, value); } } /// <summary> /// Static part of dependency property WaterMark /// </summary> public static readonly DependencyProperty WaterMarkProperty = DependencyProperty.Register("WaterMark", typeof(string), typeof(WaterMarkedTextBox), new PropertyMetadata(""));
Все, пишем обработку загрузки компонента, получения фокуса ввода и потери его:
void WaterMarkedTextBox_Loaded(object sender, RoutedEventArgs e) { var grid = (Grid)VisualTreeHelper.GetChild(this, 0); TextBox innerTextBox = (TextBox)grid.Children[0]; innerTextBox.GotFocus += WaterMarkedTextBox_GotFocus; innerTextBox.LostFocus += WaterMarkedTextBox_LostFocus; ChangeWatermarkTextVisibility(); } void WaterMarkedTextBox_LostFocus(object sender, RoutedEventArgs e) { _isFocused = false; ChangeWatermarkTextVisibility(); } void WaterMarkedTextBox_GotFocus(object sender, RoutedEventArgs e) { _isFocused = true; ChangeWatermarkTextVisibility(); }
Ну и самый последний метод, для изменения видимости подсказки:
private void ChangeWatermarkTextVisibility() { var grid = (Grid)VisualTreeHelper.GetChild(this, 0); TextBlock watermarkText = (TextBlock)grid.Children[1]; if (!string.IsNullOrEmpty(Text) || _isFocused) { watermarkText.Visibility = Visibility.Collapsed; } else { watermarkText.Visibility = Visibility.Visible; } }
Собираем решение.
Т.к. я в качестве исходного проекта взял Blank App, то на главную форму внес вот такую разметку:
<Page x:Class="App11.MainPage" xmlns:MyControls="using:MyControls" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App11" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <StackPanel Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <TextBlock Text="Укажите сотрудника:" /> <MyControls:WaterMarkedTextBox WaterMark="Введите часть ФИО и нажмите Enter" /> </StackPanel> </Page>
Чтобы не думать о подключении namespace, я обычно новые компоненты перетягиваю на форму из панели Tools:
Ну а как все это выглядит, можно посмотреть в первой картинке этого поста, ну или повторив мои действия и запустив приложение.
ссылка на оригинал статьи http://habrahabr.ru/post/163135/
Добавить комментарий