This article has been localized into Portuguese by the community.
Criando uma caixa de diálogo de entrada personalizado
Nos últimos artigos, analisamos os diálogos internos do WPF, mas criar o seu é quase tão fácil quanto. Na verdade, você só precisa criar uma janela, colocar os controles necessários nela e depois mostrá-la.
No entanto, há algumas coisas que você deve lembrar ao criar diálogos, para garantir que seu aplicativo funcione como outros aplicativos do Windows. Neste artigo, criaremos uma caixa de diálogo muito simples para fazer uma pergunta ao usuário e depois retornar a resposta, enquanto discutimos as várias boas práticas que você deve seguir.
Criando o diálogo
Para este diálogo em particular, eu só queria um Label dizendo ao usuário quais informações nós precisamos dele, um TextBox para inserir a resposta e, em seguida, os botões Ok e Cancel. Eu decidi adicionar um ícone ao diálogo também, por boa aparência. Aqui está o resultado final:
E aqui está o código para a caixa de diálogo:
<Window x:Class="WpfTutorialSamples.Dialogs.InputDialogSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Input" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen"
ContentRendered="Window_ContentRendered">
<Grid Margin="15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Source="/WpfTutorialSamples;component/Images/question32.png" Width="32" Height="32" Grid.RowSpan="2" Margin="20,0" />
<Label Name="lblQuestion" Grid.Column="1">Question:</Label>
<TextBox Name="txtAnswer" Grid.Column="1" Grid.Row="1" MinWidth="250">Answer</TextBox>
<WrapPanel Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Right" Margin="0,15,0,0">
<Button IsDefault="True" Name="btnDialogOk" Click="btnDialogOk_Click" MinWidth="60" Margin="0,0,10,0">_Ok</Button>
<Button IsCancel="True" MinWidth="60">_Cancel</Button>
</WrapPanel>
</Grid>
</Window>
using System;
using System.Windows;
namespace WpfTutorialSamples.Dialogs
{
public partial class InputDialogSample : Window
{
public InputDialogSample(string question, string defaultAnswer = "")
{
InitializeComponent();
lblQuestion.Content = question;
txtAnswer.Text = defaultAnswer;
}
private void btnDialogOk_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void Window_ContentRendered(object sender, EventArgs e)
{
txtAnswer.SelectAll();
txtAnswer.Focus();
}
public string Answer
{
get { return txtAnswer.Text; }
}
}
}
O código é bem simples, mas aqui estão as coisas que você deve prestar uma atenção especial:
XAML
Na parte do XAML, Eu usei um Grid para posicionar os controles - até aqui nada demais. Eu removi as propriedades de Largura e Altura da Janela ao invés de defini-las automaticamente ao redimensionar para caber o conteúdo - isso faz sentindo em uma caixa de diálogo, assim você não tem que fazer um ajuste fino para fazer tudo aparecer certo. Ao invés disso, use margens e tamanhos mínimos para garantir que as coisas apareçam da forma como você queria, enquanto ainda permite ao usuário redefinir o tamanho da caixa de diálogo.
Outra propriedade que eu mudei na janela é a propriedade WindowStartupLocation. Para um diálogo como este, e provavelmente para a maioria das outras janelas não principais, você deve alterar esse valor para CenterScreen ou CenterOwner, para alterar o comportamento padrão onde sua janela aparecerá em uma posição decidida pelo Windows, a menos que você especifique manualmente Top e Left propriedades para ele.
Também preste atenção especial às duas propriedades que usei nos botões de diálogo: IsCancel e IsDefault. IsCancel diz ao WPF que, se o usuário clicar nesse botão, o DialogResult da janela deverá ser definido como false, o que também fechará a janela. Isso também garante que o usuário possa pressionar a tecla Esc no teclado para fechar a janela, algo que sempre deve ser possível em uma caixa de diálogo do Windows.
A propriedade IsDefault dá foco ao botão Ok e também garante que, se o usuário pressionar a tecla Enter no teclado, esse botão será ativado. No entanto, é necessário um manipulador de eventos para definir o DialogResult, conforme descrito posteriormente.
Code-behind
Em Code-behind, alterei o construtor para obter dois parâmetros, sendo um deles opcional. Isso nos permite colocar a pergunta e a resposta padrão, se fornecida, nos controles designados da interface do usuário.
O botão Ok tem um manipulador de eventos que garante que a propriedade DialogResult especial da Janela seja definida como true quando clicada, para sinalizar ao iniciador da caixa de diálogo que o usuário aceitou o valor inserido. Não temos um para o botão Cancelar, porque o WPF manipula isso para nós quando definimos a propriedade IsCancel como true, conforme descrito acima.
Para dar foco ao TextBox ao mostrar a caixa de diálogo, inscrevi-me no evento ContentRendered, onde seleciono todo o texto no controle e, em seguida, dou foco. Se eu quisesse dar foco, poderia usar a propriedade anexada FocusManager.FocusedElement na Janela, mas, nesse caso, também quero selecionar o texto, para permitir que o usuário sobrescreva instantaneamente a resposta fornecida por padrão (se houver ).
Um último detalhe é a propriedade Answer que eu implementei. Ele simplesmente dá acesso ao valor inserido do controle TextBox, mas é uma boa prática fornecer uma propriedade com o (s) valor (es) de retorno da caixa de diálogo, em vez de acessar diretamente os controles de fora da janela. Isso também permite influenciar o valor de retorno antes de devolvê-lo, se necessário.
Usando a caixa de diálogo
Com tudo acima no lugar, nós agora estamos prontos para usar realmente nossa caixa de diálogo. Isso é uma tarefa muito simples, assim eu criei uma pequena aplicação para testá-la. Aqui está o código:
<Window x:Class="WpfTutorialSamples.Dialogs.InputDialogAppSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="InputDialogAppSample" Height="150" Width="300">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock>Hello, world. My name is:</TextBlock>
<TextBlock Name="lblName" Margin="0,10" TextAlignment="Center" FontWeight="Bold">[No name entered]</TextBlock>
<Button Name="btnEnterName" Click="btnEnterName_Click">Enter name...</Button>
</StackPanel>
</Window>
using System;
using System.Windows;
namespace WpfTutorialSamples.Dialogs
{
public partial class InputDialogAppSample : Window
{
public InputDialogAppSample()
{
InitializeComponent();
}
private void btnEnterName_Click(object sender, RoutedEventArgs e)
{
InputDialogSample inputDialog = new InputDialogSample("Please enter your name:", "John Doe");
if(inputDialog.ShowDialog() == true)
lblName.Text = inputDialog.Answer;
}
}
}
Não há nada de especial nisso - apenas alguns controles TextBlock e um botão para invocar o diálogo. No manipulador de eventos Click, instanciamos a janela InputDialogSample, fornecendo uma pergunta e uma resposta padrão, e usamos o método ShowDialog() para mostrá-la - você deve sempre usar o método ShowDialog() e não apenas Show() para um diálogo modal como este.
Se o resultado da caixa de diálogo for verdadeiro, significando que o usuário ativou o botão Ok, clicando nele ou pressionando Enter, o resultado será atribuído ao nome Rótulo. Isso é tudo que existe para isso!