Transferência de dados com vinculação de dados
Nesta lição, vamos explorar como você pode usar a vinculação de dados para a entrada de dados, mostrando e ocultando partes da interface do usuário com base no estado do aplicativo. Você também se familiarizará com o padrão INotifyPropertyChanged
completo.
Vamos expandir nossa demonstração existente com uma saudação amigável que se parece com o seguinte.
Quando você selecionar o botão Enviar, o aplicativo exibirá uma saudação simples na parte superior.
1. Abrir a solução
Se você não estiver com o Visual Studio aberto com o projeto que criou durante a última lição, abra-o agora.
2. Criar a interface do usuário para entrada de dados
A interface do usuário para entrada de dados é simples: apenas um TextBlock
, um TextBox
e um Button
em um único layout horizontal no meio da tela. A maneira mais simples para colocar horizontalmente os controles é usar um StackPanel
, semelhante a este.
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock Margin="10"
VerticalAlignment="Center"
Text="Enter your name: "/>
<TextBox Name="tbUserName"
Margin="10"
Width="150"
VerticalAlignment="Center"/>
<Button Margin="10"
VerticalAlignment="Center" >Submit</Button>
</StackPanel>
Copie o código anterior e cole-o dentro da marca Grid
do MainPage.xaml, abaixo do TextBlock
do relógio.
3. Implementar e associar a propriedade UserName
Vamos voltar a atenção para o código. Abra o MainPage.xaml.cs (você pode pressionar F7 para alternar para o code-behind e Shift+F7 para voltar ao XAML). Crie uma propriedade simples chamada UserName
.
public string UserName { get; set; }
No MainPage.xaml, podemos criar a vinculação de dados entre essa propriedade recentemente criada e o controle TextBox
. Altere o controle TextBox
adicionando o atributo Text
, desta forma:
<TextBox Name="tbUserName"
Margin="10"
Width="150"
VerticalAlignment="Center"
Text="{x:Bind UserName, Mode=TwoWay}"/>
Observação
Não confunda os controles TextBlock
e TextBox
aqui apresentados. Eles se parecem bastante no XAML, mas se você vincular o UserName
à propriedade de texto do TextBlock
em vez do TextBox
, o aplicativo não funcionará.
Com o código anterior, criamos uma vinculação de duas direções entre a propriedade Text
do TextBox
e a propriedade UserName
no código. Isso significa que sempre que o usuário inserir texto (e mover o foco para fora do TextBox
), a propriedade UserName
no código será alterada. Além disso, o texto do TextBox
será definido como o valor armazenado na propriedade UserName
ao iniciar o aplicativo ou sempre que gerarmos o evento NotifyPropertyChanged
com o "UserName"
do parâmetro propertyName
. (Não faremos isso nesta lição.)
4. Criar o manipulador de clique do botão Enviar
Em seguida, na área de design, clique duas vezes no botão Enviar. Isso irá automaticamente criar e abrir um evento Button_Click
no código. Button_Click
não é um nome muito bom, portanto, altere o nome do método para um mais expressivo OnSubmitClicked
. Quando você tiver terminado de digitar, clique na lâmpada ao lado da linha OnSubmitClicked
. Selecione Renomear 'Button_Clicked' como 'OnSubmitClicked' do menu. Volte ao XAML, verifique se o XAML do botão agora tem esta aparência.
<Button Margin="10"
VerticalAlignment="Center"
Click="OnSubmitClicked">Submit</Button>
Volte ao code-behind para que possamos exibir uma caixa de diálogo simples quando o botão for pressionado. Adicione o seguinte código ao método OnSubmitClicked
:
var dlg = new Windows.UI.Popups.MessageDialog($"Hello {UserName}!");
_ = dlg.ShowAsync();
Se você não estiver familiarizado com a sintaxe $"Hello {Username}"
, ela é o equivalente a "Hello " + UserName + "!"
ou String.Format("Hello {0}!", UserName)
. Esse recurso mais conciso e legível é chamado de interpolação de cadeia de caracteres e foi introduzido no C# 6.
O _
é uma variável de descarte. Ele é usado para indicar que o valor retornado do método ShowAsync
não é usado. O método ShowAsync
retorna um objeto Task
, que é um espaço reservado para uma tarefa que será concluída no futuro. Em nosso caso, não precisamos aguardar a conclusão da tarefa, então podemos descartar o valor retornado.
5. Executar o aplicativo
Vamos conferir o que fizemos até agora. Execute o aplicativo pressionando F5 ou Ctrl+F5. Insira seu nome, selecione o botão Enviar; uma caixa de diálogo deverá aparecer.
6. Implementar a propriedade IsNameNeeded
Se você fechar a caixa de diálogo, ainda verá a parte da entrada do nome da interface do usuário exibida. Isso não é o que queremos. Será necessário ocultar o formulário depois que ele for preenchido com êxito. Vamos fazer isso na próxima etapa usando a vinculação de dados.
Abra o MainPage.xaml.cs e crie uma propriedade para indicar se ainda é necessário inserir o nome do usuário. Adicione o seguinte código dentro da classe MainPage
:
private bool _isNameNeeded = true;
public bool IsNameNeeded
{
get { return _isNameNeeded; }
set
{
if (value != _isNameNeeded)
{
_isNameNeeded = value;
PropertyChanged?.Invoke(
this, new PropertyChangedEventArgs(nameof(IsNameNeeded)));
}
}
}
Ele se parece com uma propriedade booliana bastante padronizada com um campo de suporte e um valor padrão de true
, até chegarmos ao setter. Em primeiro lugar, o setter da propriedade verifica se o novo valor é igual ao antigo. Se for, não é necessário fazer nada. Se nada tiver mudado, você não precisará entrar em um processo demorado de recalcular o layout e renderizar os controles novamente. No entanto, se o valor da propriedade foi alterado, você precisa informar à interface do usuário usando o evento PropertyChanged
.
No código anterior, é possível ver o padrão da interface INotifyPropertyChanged:
- Verifique se o valor foi alterado.
- Se sim, defina o novo valor.
- Notifique a interface do usuário.
Depois que você tiver notificado a interface do usuário (supondo que o modo de vinculação esteja definido como OneWay
ou TwoWay
), ela chamará o getter da propriedade, receberá o novo valor e alterará a interface do usuário de forma adequada.
7. Ocultar o formulário depois que o botão de envio for selecionado
Neste caso, queremos que o formulário de entrada de nome fique visível somente até que o botão Enviar seja selecionado. Em seguida, ele desaparecerá assim que a mensagem de saudação for mostrada. Vamos alterar o método OnSubmitClicked
adicionando este código ao início:
if (string.IsNullOrEmpty(UserName))
{
return;
}
IsNameNeeded = false;
Em primeiro lugar, é realizada uma verificação rápida, pois não aceitamos mais um nome de usuário vazio aqui. Depois que o nome for inserido, IsNameNeeded
é definido como false
, e o aplicativo prosseguirá a fim de exibir a caixa de diálogo de mensagem. Definir o valor de IsNameNeeded
aciona o evento NotifyPropertyChanged
e notifica a interface do usuário.
Terminamos, assim, o código para ocultar a interface do usuário. Vamos voltar ao XAML.
No XAML, é preciso ocultar o TextBlock
, o TextBox
e o Button
quando o IsNameNeeded
for False. Ou podemos apenas ocultar o contêiner deles, o StackPanel
, em uma única etapa. Basta adicionar o atributo Visibility
ao StackPanel
, desta maneira:
Visibility="{x:Bind IsNameNeeded, Mode=OneWay}"
Execute o aplicativo, insira seu nome no TextBox
e verifique se o formulário de entrada de fato desaparece quando você seleciona o botão Enviar.
8. Usar a vinculação de interface do usuário a interface do usuário para exibir a saudação
Vamos substituir a MessageDialog
por uma exibição mais permanente: um TextBlock
no canto superior esquerdo. Adicione um novo TextBlock
ao controle principal Grid
no XAML.
<TextBlock Text="{x:Bind sys:String.Format('Hello {0}!', tbUserName.Text), Mode=OneWay}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"/>
Há muitas novas coisas acontecendo aqui. Vamos detalhar a vinculação do atributo Text
.
Para avaliar o valor da propriedade Text
no TextBlock
, o sistema chama o método interno String.Format
com a cadeia de caracteres de formato "Hello {0}"
. O objeto a ser formatado será tbUserName.Text
(em outras palavras, a propriedade Text
no controle tbUserName
). O modo de vinculação é definido como OneWay
, ou seja, o TextBlock
receberá s dados da propriedade Text
do TextBox
.
Isso é chamado de associação de interface do usuário à interface do usuário, pois a origem e o destino da associação de dados estão na interface do usuário. Para vê-la funcionando, é preciso definir o namespace sys
(que contém o método System.Format
). Adicione a seguinte linha à marca do Page
da raiz no XAML:
xmlns:sys="using:System"
Agora, ao executar o aplicativo, você verá que a saudação é atualizada toda vez que uma tecla é pressionada. Você nem precisa remover o foco dos TextBox
ou selecionar o botão Enviar.
Em um aplicativo real, a exibição do nome do usuário não aconteceria por meio da vinculação de interface do usuário à interface do usuário. Você provavelmente vincularia à propriedade DisplayName
da classe User
ou algo semelhante.
9. Ocultar a saudação até que o botão Enviar seja selecionado
Por mais interessante que pareça ter a atualização de saudação ao digitar, o texto "Olá!" na inicialização pode parecer não profissional. É preferível que a saudação TextBlock
permaneça invisível até que o botão Enviar seja selecionado.
Para calcular se a saudação está visível, usaremos um método chamado GetGreetingVisibility
e iremos adicioná-lo à classe MainPage
.
public Visibility GetGreetingVisibility()
{
return IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;
}
Você talvez tenha observado que ao ocultar o StackPanel
, estávamos vinculando um valor bool
à propriedade Visibility
(que tem um tipo de UIElement.Visibility
). Vincular Visibility
a um valor bool
é tão comum que a Microsoft criou uma conversão padrão entre os dois, e é por isso que não tivemos nenhum tipo de erro de conversão anteriormente. No entanto, essa conversão automática só funciona com propriedades, portanto, o método GetGreetingVisibility()
deverá retornar UIElement.Visibility
em vez de um valor booliano.
Assim como com as propriedades, precisamos usar o evento PropertyChanged
para notificar a interface do usuário quando quisermos que ela avalie novamente o método. Então, vamos adicionar esta linha ao final do método OnSubmitClicked
.
PropertyChanged?.Invoke(this,
new PropertyChangedEventArgs(nameof(GetGreetingVisibility)));
Como etapa final, vamos realmente executar a vinculação adicionando o atributo Visibility
à saudação TextBlock
. No MainPage.xaml, edite o TextBlock
de forma que esse tenha a aparência seguinte:
<TextBlock Text="{x:Bind sys:String.Format('Hello {0}!', tbUserName.Text), Mode=OneWay}"
Visibility="{x:Bind GetGreetingVisibility(), Mode=OneWay}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"/>
Observe que não precisamos adicionar nenhuma referência de namespace à chamada GetGreetingVisibility()
, porque ela é um membro da própria classe MainPage
.
Por fim, para deixar de exibir o MessageDialog
, comente as linhas a seguir do método OnSubmitClicked
.
// var dlg = new Windows.UI.Popups.MessageDialog($"Hello {UserName}!");
// dlg.ShowAsync();
Agora está tudo pronto para executar o aplicativo e aproveitar as mensagens de saudação.
Resumo
Nesta lição, você viu como a vinculação de dados torna mais fácil transferir os dados entre a interface do usuário e seu código ou entre dois elementos da interface do usuário. No entanto, tivemos de escrever muitos códigos, especialmente ao invocar o evento PropertyChanged
nos setters da propriedade. Na próxima lição, você criará uma classe do auxiliar para simplificar o uso do padrão INotifyPropertyChanged
.
Nesta lição, vamos explorar como você pode usar a vinculação de dados para a entrada de dados, mostrando e ocultando partes da interface do usuário com base no estado do aplicativo. Você também se familiarizará com o padrão INotifyPropertyChanged
completo e aprenderá mais sobre DataContext
.
Vamos expandir nossa demonstração existente com uma saudação amigável que se parece com o seguinte.
Quando você selecionar o botão Enviar, o aplicativo exibirá uma saudação simples na parte superior.
1. Criar um DataContext para toda a janela
Se você não estiver com o Visual Studio aberto com o projeto que criou durante a última lição, abra-o agora.
Na lição anterior, criamos uma classe Clock
dedicada cuja instância estava sendo criada dentro de TextBlock
que exibia o relógio. Essa classe Clock
continha a lógica de negócios do relógio em si. Mas geralmente é necessário abranger muito mais funcionalidades em uma tela e seria entediante definir a DataContext
para cada controle na interface do usuário.
Felizmente, a DataContext
foi projetada para poder ser aplicada na árvore XAML inteira ou apenas em uma parte dela. Um atributo chave da DataContext
é que ele é herdada pela árvore XAML inteira, mas pode ser substituída em qualquer ponto para uma subárvore específica.
Vamos ver como funciona na prática. Crie uma classe chamada MainWindowDataContext
e verifique se ela e seu construtor são públicos:
namespace DatabindingSampleWPF
{
public class MainWindowDataContext
{
public MainWindowDataContext()
{
}
}
}
Agora defina uma instância dessa classe para ser o DataContext
para a Window
inteira. Em MainWindow.xaml, adicione isto exatamente após a marca de abertura Window
:
<Window.DataContext>
<local:MainWindowDataContext />
</Window.DataContext>
Neste ponto, o Visual Studio pode indicar que a classe DatabindingSampleWPF.MainWindowDataContext
não existe. Isso ocorre porque o projeto não foi compilado desde que você adicionou essa classe. Você pode corrigir esse erro compilando o projeto.
Vamos revisar o que foi visto até agora. O DataContext
está definido no nível Window
(raiz). Essa instância do objeto será o DataContext
de todos os controles dentro da Window
. A única exceção é o TextBlock
que exibe o relógio, que já tem seu próprio conjunto de DataContext
, o que substitui o DataContext
global herdado. Se este TextBlock
tiver outros controles dentro da hierarquia, eles também herdariam o objeto Clock
definido no DataContext
de TextBlock
.
2. Criar a interface do usuário para entrada de dados
A interface do usuário para entrada de dados é simples: apenas um TextBlock
, um TextBox
e um Button
em um único layout horizontal no meio da tela. A maneira mais simples para colocar horizontalmente os controles é usar um StackPanel
, semelhante a este.
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock Margin="10"
VerticalAlignment="Center"
Text="Enter your name:"/>
<TextBox Name="tbName"
Margin="10"
Width="150"
VerticalAlignment="Center"/>
<Button Margin="10"
VerticalAlignment="Center">Submit</Button>
</StackPanel>
Copie o código anterior e cole-o dentro da marca Grid
do MainPage.xaml, abaixo do TextBlock
do relógio.
3. Implementar e associar a propriedade UserName
Vamos voltar a atenção para o código. Abra MainWindowDataContext.cs
e crie uma propriedade chamada UserName
.
public string? UserName { get; set; }
Retornando para MainWindow.xaml
, podemos criar a vinculação de dados entre a propriedade UserName
e o controle TextBox
. Altere o controle TextBox
adicionando o atributo Text
, desta forma:
<TextBox Name="tbUserName"
Margin="10"
Width="150"
VerticalAlignment="Center"
Text="{Binding UserName, Mode=TwoWay}"/>
Observação
Não confunda os controles TextBlock
e TextBox
aqui apresentados. Eles se parecem bastante no XAML, mas se você vincular o UserName
à propriedade de texto do TextBlock
em vez do TextBox
, o aplicativo não funcionará.
Com o código anterior, criamos uma vinculação bidirecional entre a propriedade Text
do TextBox
e a propriedade UserName
no código. Isso significa que sempre que o usuário inserir texto (e mover o foco para fora do TextBox
), a propriedade UserName
no código será alterada. Além disso, o texto do TextBox
será definido como o valor armazenado na propriedade UserName
ao iniciar o aplicativo ou sempre que gerarmos o evento NotifyPropertyChanged
com o "UserName"
do parâmetro propertyName
. (Não faremos isso nesta lição.)
Observação
No WPF, o modo de vinculação é determinado automaticamente para as situações mais comuns. Por exemplo, se você estiver associando à propriedade Text
de uma TextBox
, o WPF definirá o modo de associação como TwoWay
por padrão. Isso significa que podemos até mesmo ignorar ao especificar o modo de vinculação e poderíamos simplesmente gravar Text={Binding UserName}
. Aprenda mais sobre modos de vinculação aqui.
4. Criar o manipulador de clique do botão Enviar
Em seguida, na área de design, clique duas vezes no botão Enviar. Isso vai criar automaticamente um evento Button_Click
em MainWindow.xaml.cs
e abrir o arquivo. Button_Click
não é um nome muito descritivo, portanto, altere o nome do método para OnSubmitClicked
. Quando terminar de digitar, clique dica de chave de fenda ao lado da linha OnSubmitClicked
e selecione Renomear 'Button_Clicked' to 'OnSubmitClicked' no menu. Volte ao XAML, verifique se o XAML do botão agora tem esta aparência:
<Button Margin="10"
VerticalAlignment="Center"
Click="OnSubmitClicked">Submit</Button>
Volte ao code-behind para que possamos exibir uma caixa de diálogo simples quando o botão for pressionado. Adicione uma propriedade de conveniência na parte superior da classe MainWindow
que nos permita acessar facilmente o objeto MainWindowDataContext
definido como o DataContext
da MainWindow
inteira.
private MainWindowDataContext DC => (MainWindowDataContext)DataContext;
Depois adicione o seguinte código ao método OnSubmitClicked
:
MessageBox.Show($"Hello {DC.UserName}!");
O valor do texto inserido na TextBox
é armazenado na propriedade MainWindowDataContext.UserName
. A primeira linha armazena uma referência para o objeto MainWindowDataContext
em uma variável temporária. A segunda linha exibe uma caixa de mensagem com a saudação.
Se você não estiver familiarizado com a sintaxe $"Hello {Username}"
, ela é o equivalente a "Hello " + UserName + "!"
ou String.Format("Hello {0}!", UserName)
. Essa sintaxe mais concisa e legível é chamada de interpolação de cadeia de caracteres e foi introduzida no C# 6.
5. Executar o aplicativo
Vamos testar o que fizemos até agora! Execute o aplicativo pressionando F5 ou Ctrl+F5. Insira seu nome, selecione o botão Enviar; uma caixa de diálogo deverá aparecer.
6. Implementar a propriedade IsNameNeeded
Observe que a parte de entrada do nome da interface do usuário ainda será exibida depois que o botão Enviar for pressionado. Será necessário ocultar o formulário depois que ele for preenchido com êxito. Vamos fazer isso na próxima etapa usando a vinculação de dados.
Primeiro, abra MainWindowDataContext.cs e faça MainWindowDataContext
herdar de INotifyPropertyChanged
, exatamente como fizemos com a classe Clock
.
using System.ComponentModel;
public class MainWindowDataContext : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
Em seguida, crie uma propriedade para indicar se ainda é necessário inserir o nome do usuário. Adicione o seguinte código dentro da classe MainWindowDataContext
:
private bool _isNameNeeded = true;
public bool IsNameNeeded
{
get { return _isNameNeeded; }
set
{
if (value != _isNameNeeded)
{
_isNameNeeded = value;
PropertyChanged?.Invoke(
this, new PropertyChangedEventArgs(nameof(IsNameNeeded)));
}
}
}
Ele se parece com uma propriedade booliana bastante padronizada com um campo de suporte e um valor padrão de true
, até chegarmos ao setter. Em primeiro lugar, o setter da propriedade verifica se o novo valor é igual ao antigo. Se for, não é necessário fazer nada. Se nada tiver mudado, você não precisará entrar em um processo demorado de recalcular o layout e renderizar os controles novamente. No entanto, se o valor da propriedade foi alterado, você precisa informar à interface do usuário usando o evento PropertyChanged
.
No código anterior, é possível ver o padrão da interface INotifyPropertyChanged:
- Verifique se o valor foi alterado.
- Se sim, defina o novo valor.
- Notifique a interface do usuário.
Depois que você tiver notificado a interface do usuário (supondo que o modo de vinculação esteja definido como OneWay
ou TwoWay
), ela chamará o getter da propriedade, receberá o novo valor e alterará a interface do usuário de forma adequada.
7. Ocultar o formulário depois que o botão de envio for selecionado
Neste caso, queremos que o formulário de entrada de nome fique visível somente até que o botão Enviar seja selecionado. Em seguida, ele desaparecerá assim que a mensagem de saudação for mostrada. Vamos alterar o método OnSubmitClicked
adicionando este código ao início:
if (string.IsNullOrWhiteSpace(DC.UserName))
{
return;
}
DC.IsNameNeeded = false;
Em primeiro lugar, é realizada uma verificação rápida, pois não aceitamos mais um nome de usuário vazio aqui. Depois que o nome for inserido, IsNameNeeded
é definido como false
, e o aplicativo prosseguirá a fim de exibir a caixa de diálogo de mensagem. Definir o valor de IsNameNeeded
aciona o evento NotifyPropertyChanged
e notifica a interface do usuário.
Terminamos, assim, o código para ocultar a interface do usuário. Vamos voltar ao XAML.
No XAML, é preciso ocultar o TextBlock
, o TextBox
e o Button
quando o IsNameNeeded
for False. Ou podemos apenas ocultar o contêiner deles, o StackPanel
, em uma única etapa. Adicione o atributo Visibility
ao StackPanel
, desta maneira:
Visibility="{Binding IsNameNeeded, Converter={StaticResource BooleanToVisibilityConverter}}"
Uma vinculação consiste em duas partes. A primeira parte especifica o caminho da vinculação, que indica a propriedade IsNameNeeded
do objeto MainWindowDataContext
definido como o DataContext
da Window
inteira.
Mas a propriedade IsNameNeeded
é booliana, enquanto Visibility
é do tipo System.Windows.Visibility, que é enum
. É necessário fazer uma conversão entre os dois. Essa conversão é tão comum que o WPF tem uma classe auxiliar interna chamada BooleanToVisibilityConverter
. É necessário criar uma instância dessa classe e referenciá-la por meio da declaração de vinculação.
Criaremos uma instância desta classe em XAML como um recurso do objeto Window
. Cada FrameworkElement
pode ter sua própria coleção de recursos com uma chave que identifica todos os recursos na coleção. O BooleanToVisibilityConverter
na vinculação anterior é essa chave, que aponta para um objeto BooleanToVisibilityConverter
dentro da coleção de recursos. A coleção de recursos pode ser definida ao adicionar o seguinte código para o Window
, logo após a marca de abertura:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
Execute o aplicativo, insira seu nome no TextBox
e verifique se o formulário de entrada de fato desaparece quando você seleciona o botão Enviar.
8. Usar a vinculação de interface do usuário a interface do usuário para exibir a saudação
Vamos substituir a MessageDialog
por uma exibição mais permanente: um TextBlock
no canto superior esquerdo. Adicione um novo TextBlock
ao controle principal Grid
no XAML.
<TextBlock Text="{Binding Text, ElementName=tbName, StringFormat='Hello {0}!'}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"/>
Há várias novidades introduzidas nessa nova TextBlock
. Vamos detalhar a vinculação do atributo Text
.
Para avaliar o valor da propriedade Text
no TextBlock
, o sistema chama o método interno String.Format com a cadeia de caracteres de formato "Hello {0}"
. O objeto a ser formatado será tbName.Text
(em outras palavras, a propriedade Text
no controle tbName
). O modo de vinculação é definido automaticamente como OneWay
, ou seja, o TextBlock
receberá s dados da propriedade Text
do TextBox
.
Isso é chamado de associação de interface do usuário à interface do usuário, pois a origem e o destino da associação de dados estão na interface do usuário. Para ver isso em ação, basta executar o aplicativo. Observe como a saudação é atualizada a cada pressionamento de tecla. Você nem precisa remover o foco dos TextBox
ou selecionar o botão Enviar.
Em um aplicativo real, a exibição do nome do usuário não aconteceria por meio da vinculação de interface do usuário à interface do usuário. Você provavelmente vincularia à propriedade DisplayName
de uma classe User
ou algo semelhante.
9. Ocultar a saudação até que o botão Enviar seja selecionado
Por mais interessante que pareça ter a atualização de saudação ao digitar, o texto "Olá!" na inicialização pode parecer não profissional. É preferível que a saudação TextBlock
permaneça invisível até que o botão Enviar seja selecionado.
Para calcular se a saudação está visível, usaremos uma propriedade chamada GreetingVisibility
e a adicionaremos à classe MainWindowDataContext
.
public Visibility GreetingVisibility => IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;
Você também precisará adicionar o namespace System.Windows
a using
s em MainWindowDataContext
.
Talvez você se lembre de que, antes, quando ocultamos o StackPanel
, estávamos vinculando um valor bool
à propriedade Visibility
(que tem um tipo de System.Windows.Visibility
). No entanto, podemos ignorar BooleanToVisibilityConverter
quando a origem da vinculação já é do tipo de dados correto.
Como antes, precisamos usar o evento PropertyChanged
para notificar a interface do usuário quando quisermos que ela avalie novamente o GreetingVisibility
. Então, vamos adicionar essa linha ao final do bloco if
no setter IsNameNeeded
.
PropertyChanged?.Invoke(
this, new PropertyChangedEventArgs(nameof(GreetingVisibility)));
Isso garante que, sempre que IsNameNeeded
é alterado, dois eventos PropertyChanged
sejam gerados: um para a própria propriedade IsNameNeeded
e outro para a propriedade calculada GreetingVisibility
, que depende de IsNameNeeded
.
Como etapa final, vamos executar a vinculação adicionando o atributo Visibility
à saudação TextBlock
. Em MainWindow.xaml
, edite TextBlock
para que fique assim:
<TextBlock Text="{Binding Text, ElementName=tbName, StringFormat='Hello {0}!'}"
Visibility="{Binding GreetingVisibility}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="10"/>
Por fim, para deixar de exibir MessageBox
, comente as linhas a seguir do método OnSubmitClicked
em MainWindow.xaml.cs
.
// MessageBox.Show($"Hello {DC.UserName}!");
Agora está tudo pronto para executar o aplicativo e aproveitar as mensagens de saudação.
Resumo
Nesta lição, você viu como a vinculação de dados torna mais fácil transferir os dados entre a interface do usuário e seu código ou entre dois elementos da interface do usuário. No entanto, tivemos de escrever muitos códigos, especialmente ao invocar o evento PropertyChanged
nos setters da propriedade. Na próxima lição, você criará uma classe do auxiliar para simplificar o uso do padrão INotifyPropertyChanged
.