Элемент TextBox в WinRT

131

Ввод с клавиатуры в приложениях Windows 8 несколько усложняется появлением экранной клавиатуры, позволяющей пользователю вводить текст, прикасаясь к экрану. Хотя экранная клавиатура особенно важна для планшетов и других устройств, не имеющих физической клавиатуры, она также может вызываться как дополнение для обычной клавиатуры.

Очень важно, чтобы экранная клавиатура не исчезала и не появлялась внезапно, раздражая пользователя. По этой причине многие элементы управления - включая пользовательские - не получают ввод с клавиатуры автоматически. В противном случае системе приходилось бы активизировать экранную клавиатуру каждый раз, когда эти элементы получают фокус ввода. Соответственно, если вы создаете пользовательский элемент управления и назначаете обработчики событий KeyUp и KeyDown (или переопределяете методы OnKeyUp и OnKeyDown), выясняется, что никакой ввод ему не передается. Необходимо написать код, который предоставляет элементу управления фокус ввода.

Если вас интересует ввод только с физической клавиатуры, а экранная клавиатура вас не интересует (например, если программа предназначена только для вас или для тестирования), задача решается достаточно просто. В конструкторе своей страницы получите объект CoreWindow приложения:

CoreWindow coreWindow = Window.Current.CoreWindow;

Этот класс определяется в пространстве имен Windows.UI.Core. Затем можно назначить для этого объекта обработчики событий KeyDown и KeyUp (для клавиш на клавиатуре), а также события CharacterReceived (преобразующего нажатия клавиш в символы текста).

Если вам потребуется создать пользовательский элемент управления, получающий ввод как с физической, так и с экранной клавиатуры, процесс будет более сложным. Вам придется определить класс, производный от FrameworkElementAutomationPeer, который реализует интерфейсы ITextProvider и IValueProvider, и вернуть этот класс в переопределении метода OnCreateAutomationPeer вашего элемента управления. Разумеется, эта задача нетривиальна, но полная информация будет приведена позже.

А пока, если ваша программа нуждается в вводе текста, лучше всего воспользоваться одним из элементов управления, предназначенных специально для этой цели:

TextBox

Однострочное или многострочное поле ввода с единым шрифтом (как в традиционной Windows-программе Блокнот).

RichEditBox

Поле с возможностью форматирования текста (как в традиционной Windows-программе WordPad).

PasswordBox

Однострочное поле с маскировкой вводимых символов.

В этом кратком обсуждении я сосредоточусь на TextBox, а в следующих статьях будут приведены дополнительные примеры.

Класс TextBox определяет свойство Text, при помощи которого можно в программном коде задать или получить текущее содержимое TextBox. Свойство SelectedText содержит выделенный текст (если он есть), а свойства SelectionStart и SelectionLength обозначают смещение и длину выделения. Если значение SelectionLength равно 0, то SelectionStart содержит позицию курсора. Если свойство IsReadOnly равно true, ввод текста с клавиатуры в поле запрещен, но сохраняется возможность его выделения и копирования в буфер. Все операции копирования, вырезания и вставки осуществляются через контекстные меню. Класс TextBox определяет события TextChanged и SelectionChanged.

По умолчанию поле TextBox вводит текст только в одну строку. Это поведение можно изменить при помощи двух свойств:

Эти свойства могут задаваться независимо друг от друга. Каждое из них заставляет TextBox увеличиваться по вертикали при добавлении новых строк. Элемент управления TextBox содержит встроенный объект ScrollViewer. Если вы не хотите, чтобы поле TextBox бесконечно увеличивалось, задайте значение свойства MaxLength.

Существует несколько разновидностей экранных клавиатур, причем некоторые из них предназначены специально для ввода чисел, адресов электронной почты или URL Подходящий тип клавиатуры для элемента управления TextBox задается свойством InputScope.

Следующая программа позволяет поэкспериментировать с разными раскладками клавиатуры, а также с разными режимами многострочных экземпляров TextBox и (дополнительно) PasswordBox:

<Page ...>

    <Page.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="24" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="Margin" Value="6" />
        </Style>

        <Style TargetType="TextBox">
            <Setter Property="Width" Value="320" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="Margin" Value="0 6" />
        </Style>
    </Page.Resources>

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid HorizontalAlignment="Center">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>

            <TextBlock Text="Многострочное поле с обработкой Return, без переноса:"
                       Grid.Row="0" Grid.Column="0" />

            <TextBox AcceptsReturn="True"
                     Grid.Row="0" Grid.Column="1" />

            <TextBlock Text="Многострочное поле без обработки Return, с переносом:"
                       Grid.Row="1" Grid.Column="0" />

            <TextBox TextWrapping="Wrap"
                     Grid.Row="1" Grid.Column="1" />

            <TextBlock Text="Многострочное поле с обработкой Return и переносом:"
                       Grid.Row="2" Grid.Column="0" />

            <TextBox AcceptsReturn="True"
                     TextWrapping="Wrap"
                     Grid.Row="2" Grid.Column="1" />

            <TextBlock Text="Текстовое поле с настройками по умолчанию:"
                       Grid.Row="3" Grid.Column="0" />

            <TextBox Grid.Row="3" Grid.Column="1"
                     InputScope="Default" />

            <TextBlock Text="Поле ввода для email-адресов:"
                       Grid.Row="4" Grid.Column="0" />

            <TextBox Grid.Row="4" Grid.Column="1"
                     InputScope="EmailSmtpAddress" />

            <TextBlock Text="Поле ввода для чисел:"
                       Grid.Row="5" Grid.Column="0" />

            <TextBox Grid.Row="5" Grid.Column="1"
                     InputScope="Number" />

            <TextBlock Text="Поле поиска:"
                       Grid.Row="6" Grid.Column="0" />

            <TextBox Grid.Row="6" Grid.Column="1"
                     InputScope="Search" />

            <TextBlock Text="Поле ввода для номеров телефонов:"
                       Grid.Row="7" Grid.Column="0" />

            <TextBox Grid.Row="7" Grid.Column="1"
                     InputScope="TelephoneNumber" />

            <TextBlock Text="Поле ввода URL:"
                       Grid.Row="8" Grid.Column="0" />

            <TextBox Grid.Row="8" Grid.Column="1"
                     InputScope="Url" />

            <TextBlock Text="PasswordBox:"
                       Grid.Row="9" Grid.Column="0" />

            <PasswordBox Grid.Row="9" Grid.Column="1" />
        </Grid>
    </Grid>
</Page>

Поэкспериментируйте с этой программой, прежде чем включать многострочный режим ввода или выбирать значение InputScope.

Пройди тесты
Лучший чат для C# программистов