Transferência de dados com vinculação de dados

Concluído

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.

Screenshot of sample app with a name entry field and submit button.

Quando você selecionar o botão Enviar, o aplicativo exibirá uma saudação simples na parte superior.

Screenshot of sample app showing

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.

Screenshot of sample app with new greeting dialog box that displays

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.

Screenshot of sample app running with a name entry field and value entered of

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.

Screenshot of sample app with a name entry field and submit button.

Quando você selecionar o botão Enviar, o aplicativo exibirá uma saudação simples na parte superior.

Screenshot of sample app showing

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.

Screenshot of sample app with new greeting dialog box that displays

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.

Screenshot of sample app running with a name entry field and value entered of

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 usings 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.