WPF - O controle TextBox e a tecla ENTER/TAB
Os controles WPF nem sempre possuem as mesmas propriedades e eventos que os controles das aplicações Windows Forms e neste artigo veremos como detectar e tratar o acionamento da Tecla ENTER em aplicações WPF no controle TextBox e como fazemos para tornar o comportamento do ENTER idêntico ao do acionamento da tecla TAB.
Nos exemplos mostrados neste artigo eu estou usando o Visual Studio 2010 beta 2 mas o comportamento será o mesmo para o VS 2008.
Para criar uma aplicação WPF abra o VS e no menu File selecione New Project e a seguir o template WPF Application informe (Wpf_ENTER) o nome e clique em OK.
A representação XAML para o controle TextBox é feita pelo elemento <TextBox />. Assim para criar um controle WPF usando XAML usamos a seguinte sintaxe:
Os atributos Width e Height definem a altura e a largura do TextBox. Abaixo temos um exemplo de criação de um controle TextBox com altura e largura definidos em um Canvas:
Para posicionar um controle TextBox você deve definir os atributos Top e Left do controle Container pai que no nosso caso é o container Canvas. Abaixo vemos um exemplo onde definimos Canvas.Top e Canvas.Left:
Para definir as cores de fundo do controle e a do frente usamos os atributos BackGround e ForeGround atribuindo a cor desejada:
Podemos também definir o atributo TextWrapping que permite que o fluxo de texto quebre e continue na linha seguinte. Os valores possíveis são : Wrap , NoWrap e WrapWithOverflow
Já os atributos VerticalScrollBarVisbility e HorizontalScrollBarVisibility que definem barras de rolagem vertical e horizontal. Os valores possíveis são: Auto, Disable, Hidden e Visible.
Podemos ainda usar os atributos MaxHeight, MaxWidth, MaxLines e MaxLength do controle TextBox para restringir a altura e largura máximas, o número máximo de linhas, e o comprimento máximo do TextBox. Da mesma forma os atributos MinHeight, MinWidht, MinLines, e MinLength restringem os valores mínimos.
Para não permitir a edição em um controle TextBox defina a propriedade IsReadOnly como true.
Agora veremos algo mais interessante; como tratar o acionamento da teclar ENTER.
O controle TextBox da WPF não possui o evento KeyPress do controle Windows Forms de mesmo nome, então como podemos saber quando o usuário pressionou a tecla ENTER quando o controle TextBox tiver o foco ?
Capturando a tecla ENTER
Podemos fazer isso de muitas maneiras e eu vou mostrar um exemplo onde vamos capturar o que foi informado em um controle TextBox após o acionamento da tecla ENTER;
Na janela Window1.xaml vamos definir uma interface usando os controles TextBox, TextBlock, e ListBox no interior de um StackPanel conforme o leiaute da figura abaixo:
O objetivo é capturar o que o usuário digitar no controle TextBox1 e exibir em um controle TextBlock e incluir também em um controle ListBox.
Para exibir o que o usuário digitou no controle TextBlock eu vou usar o evento KeyDown e definir um nome para a rotina que vamos chamar no code-behind.
Isso foi definido da seguinte forma: <TextBox Width="300" Height="30" Name="textBox1" KeyDown="OnKeyDownHandler"/>
No arquivo code-behind Window1.xaml.vb devemos definir a rotina OnKeyDownHandler da seguinte forma:
Class Window1 Private Sub OnKeyDownHandler(ByVal sender As Object, ByVal e As KeyEventArgs) If (e.Key = Key.Return) Then textBlock1.Text = "Você informou : " + textBox1.Text End If End Sub End Class |
Neste código verificamos se a tecla pressionada é a tecla ENTER, e, neste caso exibimos o que foi digitado no TextBlock.
Para incluir o que foi digitado no controle ListBox vamos usar o evento PreviewKeyUp do controle TextBox definindo no arquivo code-behind o seguinte código:
Private Sub TextBox1_PreviewKeyUp(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs)_ Handles textBox1.PreviewKeyUp If (e.Key = Key.Enter) Then ListBox1.Items.Add(textBox1.Text) textBox1.Text = "" e.Handled = True End If End Sub |
O código acima verifica se a tecla ENTER foi pressionada e inclui o conteúdo do TextBox no controle ListBox.Executando o projeto iremos obter o seguinte resultado:
Fazendo a
tecla ENTER se comportar como TAB (Mudar o
foco para outro controle)
A tecla TAB é usada para mudar o foco para
outro controle. O problema é que os usuários costumam
pressionar a tecla ENTER para mudar o foco.
Para resolver este problema podemos mudar o comportamento da tecla ENTER de forma que quando ela for pressionada o foco seja movido para outro controle.
Para fazer isso vamos usar a classe TraversalRequest.
A classe TraversalRequest representa uma requisição para mover o foco para outro controle.
Essa classe é usada como um parâmetro de entrada para o método UIElement.MoveFocus.
Você irá definir propriedades na classe TraversalRequest com o objetivo de personalizar o comportamento do foco quando você solicitar que o foco seja movido para outro elemento.
Vamos incluir uma nova janela Window2.xaml no projeto e incluir nesta janela 3 controles TextBox conforme a figura abaixo:
A seguir devemos definir o arquivo code-behind Window2.xaml.vb o seguinte código:
Partial Public Class Window2 Private Sub Window1_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.KeyEventArgs) _ Handles MyBase.PreviewKeyDown Dim elemento = TryCast(e.OriginalSource, UIElement) If elemento Is Nothing Then Return End If If e.Key = Key.Enter Or e.Key = Key.Down Then elemento.MoveFocus(New TraversalRequest(FocusNavigationDirection.[Next])) End If If e.Key = Key.Up Then elemento.MoveFocus(New TraversalRequest(FocusNavigationDirection.Up)) End If End Sub End Class |
No código acima estamos usando o evento PreviewKeyDown
da janela Window1 e criando uma variável a partir do controle
atual que é indicado por e.OriginalSource, pois será
a partir dele que vamos mudar o foco;
Em seguida verificamos se a variável controle é nula , e, neste caso nada será feito.(Return)
Se a variável não for nula passamos então a verificar se a tecla ENTER foi acionada, e, em caso positivo chamamos o método MoveFocus() para mover o foco para outro controle.(TraversalRequest(FocusNavigationDirection.[Next]))
Aqui é que entra a classe TraversalRequest. Passamos uma nova instância dessa classe para o método MoveFocus() indicando a direção através da enumeração FocusNavigationDirection que pode receber os seguintes valores: Next, Previous, First, Last, Left, Right, Up e Down.
A movimentação do foco é feita de acordo com o TabOrder do formulário ou pela posição dos controles no mesmo.
Observe que no código acima tratamos a tecla ENTER e a tecla Down (Seta para baixo) para mover o foco para outro controle e a tecla UP (seta para cima) para retornar ao controle anterior.
Executando o projeto iremos obter:
Estando o foco inicialmente
no controle TextBox (1) digitamos Macoratti e... Pressionando a tecla ENTER ou a tecla
Seta para baixo o foco será movido para os Se pressionarmos a tecla seta para cima retornaremos aos controles TextBox 2 e 1. |
Uma outra forma de obter o mesmo resultado para a tecla ENTER mover o foco é definir o código abaixo no evento PreviewKeyDown da janela Window1:
Nota: Lembre-se que em uma aplicação WPF, os eventos são propagados por toda a árvore de elementos, e dessa forma , os eventos de tecla obrigatoriamente passam pela janela, independente de onde tenham sido gerados.
Private Sub Window1_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.KeyEventArgs) _ Handles MyBase.PreviewKeyDown If e.Key = Key.[Return] Then Dim direcaoFoco As FocusNavigationDirection = FocusNavigationDirection.[Next] Dim requisicao As New TraversalRequest(direcaoFoco) Dim elementoComFoco As UIElement = TryCast(Keyboard.FocusedElement, UIElement) If elementoComFoco IsNot Nothing Then elementoComFoco.MoveFocus(requisicao) End If e.Handled = True End If End Sub |
E era isso que eu tinha para escrever. Aguarde mais dicas sobre WPF.
Pegue o projeto completo aqui: Wpf_ENTER.zip
Eu sei é apenas WPF, mas eu gosto...
Referências: