Przesyłanie danych za pomocą powiązania danych

Ukończone

W tej lekcji dowiesz się, jak używać powiązania danych do wprowadzania danych, pokazywania i ukrywania fragmentów interfejsu użytkownika na podstawie stanu aplikacji. Zapoznasz się również z pełnym INotifyPropertyChanged wzorcem.

Rozszerzmy istniejącą demonstrację z przyjaznym powitaniem, które wygląda następująco.

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

Po wybraniu przycisku Prześlij aplikacja wyświetli proste powitanie u góry.

Screenshot of sample app showing

1. Otwórz rozwiązanie

Jeśli nie masz otwartego programu Visual Studio z projektem utworzonym podczas ostatniej lekcji, otwórz go teraz.

2. Tworzenie interfejsu użytkownika wpisu danych

Interfejs użytkownika wprowadzania danych jest prosty: tylko element TextBlock, a TextBoxi Button, w jednym układzie poziomym na środku ekranu. Najprostszym sposobem na umieszczenie kontrolek w poziomie jest użycie obiektu StackPanel, takiego jak .

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

Skopiuj poprzedni kod i wklej go wewnątrz Grid tagu MainPage.xaml poniżej zegara TextBlock.

3. Implementowanie i wiązanie właściwości UserName

Zwróćmy uwagę na kod. Otwórz plik MainPage.xaml.cs (możesz nacisnąć klawisz F7, aby przełączyć się do kodu z tyłu, a klawisze Shift+F7, aby wrócić do języka XAML). Utwórz prostą właściwość o nazwie UserName.

public string UserName { get; set; }

Wracając do pliku MainPage.xaml, możemy utworzyć powiązanie danych między tą nowo utworzoną właściwością a kontrolką TextBox . Zmień kontrolkę TextBoxText , dodając atrybut w następujący sposób:

<TextBox Name="tbUserName" 
         Margin="10" 
         Width="150" 
         VerticalAlignment="Center" 
         Text="{x:Bind UserName, Mode=TwoWay}"/>

Uwaga

Pamiętaj, aby nie mylić kontrolek TextBlock i TextBox w tym miejscu. Wyglądają one bardzo podobnie w języku XAML, ale jeśli powiążesz UserName właściwość text z TextBlockwłaściwością text zamiast TextBox, aplikacja nie będzie działać.

W poprzednim kodzie utworzyliśmy powiązanie dwukierunkowe między Text właściwością obiektu TextBox i UserName właściwością w kodzie. Oznacza to, że za każdym razem, gdy użytkownik wprowadza tekst (i przenosi fokus poza TextBox), UserName właściwość w kodzie ulegnie zmianie. TextBoxPonadto tekst "jest ustawiony na wartość przechowywaną we UserName właściwości podczas uruchamiania aplikacji lub za każdym razem, gdy zgłaszamy NotifyPropertyChanged zdarzenie za pomocą parametru propertyName"UserName". (W tej lekcji tego nie zrobimy).

4. Utwórz procedurę obsługi kliknięcia przycisku Prześlij

Następnie na powierzchni projektowej kliknij dwukrotnie przycisk Prześlij . Spowoduje to automatyczne utworzenie i otwarcie Button_Click zdarzenia w kodzie. Button_Click nie jest szczególnie dobrą nazwą, więc zmień nazwę metody na bardziej wyrazistą OnSubmitClicked. Po zakończeniu wpisywania kliknij żarówkę OnSubmitClicked obok wiersza. Wybierz pozycję Zmień nazwę "Button_Clicked" na "OnSubmitClicked" z menu. Wróć do kodu XAML, sprawdź, czy kod XAML przycisku wygląda teraz następująco.

<Button Margin="10" 
        VerticalAlignment="Center" 
        Click="OnSubmitClicked">Submit</Button>

Wróćmy do kodu z tyłu, wyświetlimy proste okno dialogowe po naciśnięciu przycisku. Dodaj następujący kod do metody OnSubmitClicked:

var dlg = new Windows.UI.Popups.MessageDialog($"Hello {UserName}!");
_ = dlg.ShowAsync();

Jeśli nie znasz $"Hello {Username}" składni, jest to odpowiednik "Hello " + UserName + "!" elementu lub String.Format("Hello {0}!", UserName). Ta bardziej zwięzła i czytelna funkcja jest nazywana interpolacją ciągów i została wprowadzona w języku C# 6.

Jest _ to zmienna odrzucania. Służy do wskazywania, że zwracana wartość ShowAsync metody nie jest używana. Metoda ShowAsync zwraca Task obiekt, który jest symbolem zastępczym zadania, które zostanie ukończone w przyszłości. W naszym przypadku nie musimy czekać na ukończenie zadania, więc możemy odrzucić wartość zwracaną.

5. Uruchamianie aplikacji

Sprawdźmy, co zrobiliśmy do tej pory! Uruchom aplikację, naciskając klawisz F5 lub Ctrl+F5. Wprowadź swoją nazwę, wybierz przycisk Prześlij , a okno dialogowe powinno Cię powitać.

Screenshot of sample app with new greeting dialog box that displays

6. Zaimplementuj IsNameNeeded właściwość

Jeśli zamkniesz okno dialogowe, nadal będzie widoczna część wpisu nazwy interfejsu użytkownika. To nie jest to, czego chcemy. Musimy ukryć formularz po pomyślnym wypełnieniu. Zróbmy to w następnym kroku przy użyciu powiązania danych.

Otwórz plik MainPage.xaml.cs i utwórz właściwość, aby wskazać, czy wprowadzanie nazwy użytkownika jest nadal potrzebne. Dodaj następujący kod w MainPage klasie:

private bool _isNameNeeded = true;

public bool IsNameNeeded
{
    get { return _isNameNeeded; }
    set
    {
        if (value != _isNameNeeded)
        {
            _isNameNeeded = value;
            PropertyChanged?.Invoke(
                this, new PropertyChangedEventArgs(nameof(IsNameNeeded)));
        }
    }
}

Jest to dość standardowa właściwość logiczna z polem zapasowym i wartością truedomyślną , dopóki nie zostanie wyświetlony zestaw. Ustawiająca właściwość najpierw sprawdza, czy nowa wartość jest taka sama jak stara. Jeśli tak jest, nie ma potrzeby nic robić. Jeśli nic się nie zmieniło, nie chcesz rozpoczynać długiego procesu ponownego obliczania układu i ponownego renderowania kontrolek. Jeśli jednak wartość właściwości uległa zmianie, musisz poinformować interfejs użytkownika o tym przy użyciu PropertyChanged zdarzenia.

W poprzednim kodzie można zobaczyć standardowy wzorzec interfejsu INotifyPropertyChanged :

  • Sprawdź, czy wartość została zmieniona.
  • Jeśli tak, ustaw nową wartość.
  • Powiadom interfejs użytkownika.

Po powiadomieniu interfejsu użytkownika (przy założeniu, że tryb powiązania jest ustawiony na OneWay lub TwoWay), wywołuje metodę getter właściwości, otrzymuje nową wartość i odpowiednio zmienia interfejs użytkownika.

7. Ukryj formularz po wybraniu przycisku Prześlij

W naszym przypadku chcemy, aby formularz wprowadzania nazwy był widoczny tylko do momentu wybrania przycisku Prześlij . Następnie powinien zniknąć w tym samym czasie, gdy zostanie wyświetlony komunikat powitania. Zmieńmy metodę OnSubmitClicked , dodając ten kod na początku:

if (string.IsNullOrEmpty(UserName))
{
    return;
}

IsNameNeeded = false;

Najpierw wykonywane jest szybkie sprawdzanie, ponieważ nie akceptujemy tutaj pustej nazwy użytkownika. Po wprowadzeniu IsNameNeeded nazwy jest ustawiona wartość false, a aplikacja kontynuuje wyświetlanie okna dialogowego komunikatu. Ustawienie wartości wywołania IsNameNeededNotifyPropertyChanged zdarzenia i powiadomienie interfejsu użytkownika.

Teraz skończymy z kodem, aby ukryć interfejs użytkownika. Wróćmy do kodu XAML!

Po stronie XAML musimy ukryć TextBlockwartość , , TextBoxi Button , gdy IsNameNeeded ma wartość false. Możemy też ukryć kontener , StackPanelw jednym kroku. Wystarczy dodać Visibility atrybut do StackPanelelementu , w następujący sposób:

Visibility="{x:Bind IsNameNeeded, Mode=OneWay}"

Uruchom aplikację, wprowadź swoją nazwę w pliku TextBoxi sprawdź, czy formularz wpisu rzeczywiście zniknie po wybraniu przycisku Prześlij .

8. Użyj powiązania interfejsu użytkownika do interfejsu użytkownika, aby wyświetlić powitanie

Zastąpmy element MessageDialog bardziej trwałym wyświetlaniem: a TextBlock w lewym górnym rogu. Dodaj nowy TextBlock element do głównej Grid kontrolki w języku XAML.

<TextBlock Text="{x:Bind sys:String.Format('Hello {0}!',  tbUserName.Text), Mode=OneWay}" 
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

Jest tu wiele nowych rzeczy. Odcięmy powiązanie atrybutu Text !

Aby ocenić wartość Text właściwości w TextBlockobiekcie , system wywołuje wbudowaną String.Format metodę z ciągiem "Hello {0}"formatu . Obiekt do formatowania będzie tbUserName.Text (innymi słowy, Text właściwość kontrolki tbUserName ). Tryb powiązania jest zdefiniowany jako OneWay, co oznacza, że TextBlock dane będą odbierane z TextBoxwłaściwości .s Text .

Jest to nazywane powiązaniem interfejsu użytkownika-interfejsu użytkownika, ponieważ zarówno źródło powiązania danych, jak i element docelowy znajdują się w interfejsie użytkownika. Aby zobaczyć ją w akcji, należy zdefiniować sys przestrzeń nazw (która zawiera metodę System.Format ). Dodaj następujący wiersz do tagu głównego Page w języku XAML:

xmlns:sys="using:System"

Teraz, jeśli uruchomisz aplikację, zobaczysz, że powitanie zostanie zaktualizowane przy użyciu każdej platformy keypress. Nie musisz nawet usuwać fokusu z TextBox przycisku Lub wybierać przycisk Prześlij .

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

W rzeczywistej aplikacji wyświetlanie nazwy użytkownika nie będzie odbywać się za pomocą powiązania interfejsu użytkownika-interfejsu użytkownika. Prawdopodobnie wiązałbyś się z DisplayName właściwością User klasy lub podobnej.

9. Ukryj powitanie do momentu wybrania opcji Prześlij

Tak fajnie, jak wygląda na to, że aktualizacja powitania podczas wpisywania: "Hello!" tekst podczas uruchamiania może być wyświetlany jako nieprofesjonalny. Najlepiej byłoby, aby powitanie TextBlock było niewidoczne do momentu wybrania przycisku Prześlij .

Aby obliczyć, czy powitanie jest widoczne, użyj metody o nazwie GetGreetingVisibilityi dodaj ją do MainPage klasy .

public Visibility GetGreetingVisibility()
{
    return IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;
}

Można zauważyć, że podczas ukrywania StackPanelelementu element , wiązaliśmy wartość Visibility z właściwością bool (która ma typ UIElement.Visibility). Powiązanie wartości z Visibility wartością bool jest tak powszechne, że firma Microsoft utworzyła domyślną konwersję między nimi, dlatego nie otrzymaliśmy wcześniej żadnych błędów konwersji typów. Jednak ta automatyczna konwersja działa tylko dla właściwości, więc GetGreetingVisibility() metoda musi zwracać UIElement.Visibility zamiast wartości logicznej.

Podobnie jak we właściwościach, musimy użyć PropertyChanged zdarzenia, aby powiadomić interfejs użytkownika, gdy chcemy ponownie ocenić metodę. Dodajmy więc ten wiersz na końcu OnSubmitClicked metody .

PropertyChanged?.Invoke(this, 
    new PropertyChangedEventArgs(nameof(GetGreetingVisibility)));

Ostatnim krokiem jest wykonanie powiązania przez dodanie atrybutu Visibility do powitania TextBlock. W pliku MainPage.xaml zmodyfikuj plik TextBlock tak, aby wyglądał następująco:

<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"/>

Pamiętaj, że nie musieliśmy dodawać żadnych odwołań przestrzeni nazw do wywołania GetGreetingVisibility() , ponieważ jest to składowa MainPage samej klasy.

Na koniec, aby zatrzymać wyświetlanie MessageDialogelementu , oznacz jako komentarz następujące wiersze z OnSubmitClicked metody .

// var dlg = new Windows.UI.Popups.MessageDialog($"Hello {UserName}!");
// dlg.ShowAsync();

Teraz możesz uruchomić aplikację i cieszyć się swoimi wiadomościami powitania.

Podsumowanie

W tej lekcji pokazano, jak powiązanie danych ułatwia transfer danych między interfejsem użytkownika a kodem lub między dwoma elementami interfejsu użytkownika. Jednak istnieje wiele kodu do zapisania, zwłaszcza podczas wywoływania PropertyChanged zdarzenia w zestawerach właściwości. W następnej lekcji utworzysz klasę pomocnika, aby uprościć korzystanie ze INotifyPropertyChanged wzorca.

W tej lekcji dowiesz się, jak używać powiązania danych do wprowadzania danych, wyświetlania i ukrywania sekcji interfejsu użytkownika na podstawie stanu aplikacji. Zapoznasz się również z pełnym INotifyPropertyChanged wzorcem i dowiesz się więcej o DataContextsystemie .

Rozszerzmy istniejącą demonstrację z przyjaznym powitaniem, które wygląda następująco.

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

Po wybraniu przycisku Prześlij aplikacja wyświetli proste powitanie u góry.

Screenshot of sample app showing

1. Tworzenie obiektu DataContext obejmującego całe okno

Jeśli nie masz otwartego programu Visual Studio z projektem utworzonym podczas ostatniej lekcji, otwórz go teraz.

W poprzedniej lekcji utworzyliśmy dedykowaną Clock klasę, która była tworzona w obrębie TextBlock wyświetlanego zegara. Ta Clock klasa zawierała logikę biznesową dla samego zegara. Jednak często trzeba obejmować znacznie więcej funkcji ekranu i byłoby żmudne ustawienie DataContext dla każdej kontrolki w interfejsie użytkownika.

Na szczęście został zaprojektowany tak, DataContext aby można było zastosować go do całego drzewa XAML — lub tylko jego części. Kluczowym atrybutem DataContext jest to, że jest dziedziczony w całym drzewie XAML, ale można go zastąpić w dowolnym momencie dla określonego poddrzewa.

Zobaczmy to w praktyce. Utwórz nową klasę o nazwie MainWindowDataContexti upewnij się, że klasa i jej konstruktor są publiczne:

namespace DatabindingSampleWPF
{
    public class MainWindowDataContext
    {
        public MainWindowDataContext()
        {
        }
    }
}

Teraz ustaw wystąpienie tej klasy na DataContext wartość dla całej Windowklasy . W pliku MainWindow.xaml dodaj to bezpośrednio po tagu otwierania Window :

<Window.DataContext>
    <local:MainWindowDataContext />
</Window.DataContext>

W tym momencie program Visual Studio może wskazywać, że klasa DatabindingSampleWPF.MainWindowDataContext nie istnieje. Jest to spowodowane tym, że projekt nie został skompilowany od czasu dodania tej klasy. Ten błąd można naprawić, kompilując projekt.

Sprawdźmy, co mamy do tej pory. Parametr DataContext jest ustawiany na Window poziomie (głównym). To wystąpienie obiektu będzie DataContext dla każdej kontrolki wewnątrz obiektu Window. Jedynym wyjątkiem jest TextBlock wyświetlanie zegara, który ma już własny DataContext zestaw, a tym samym zastąpienie dziedziczonego globalnego DataContext. Jeśli w TextBlock hierarchii znajdują się dodatkowe kontrolki, będą one również dziedziczyć Clock obiekt ustawiony na DataContextTextBlockobiekcie .

2. Tworzenie interfejsu użytkownika wpisu danych

Interfejs użytkownika wprowadzania danych jest prosty: tylko element TextBlock, a TextBoxi Button w jednym układzie poziomym w środku ekranu. Najprostszym sposobem na umieszczenie kontrolek w poziomie jest użycie obiektu StackPanel, takiego jak .

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

Skopiuj poprzedni kod i wklej go wewnątrz Grid tagu MainPage.xaml poniżej zegara TextBlock.

3. Implementowanie i wiązanie właściwości UserName

Zwróćmy uwagę na kod. Otwórz plik MainWindowDataContext.csi utwórz nową właściwość o nazwie UserName.

public string? UserName { get; set; }

Wróć do MainWindow.xamlelementu , możemy utworzyć powiązanie danych między właściwością UserName a kontrolką TextBox . Zmień kontrolkę TextBoxText , dodając atrybut w następujący sposób:

<TextBox Name="tbUserName" 
         Margin="10" 
         Width="150" 
         VerticalAlignment="Center" 
         Text="{Binding UserName, Mode=TwoWay}"/>

Uwaga

Pamiętaj, aby nie mylić kontrolek TextBlock i TextBox w tym miejscu. Wyglądają one bardzo podobnie w języku XAML, ale jeśli powiążesz UserName właściwość text z TextBlockwłaściwością text zamiast TextBox, aplikacja nie będzie działać.

W poprzednim kodzie utworzyliśmy dwukierunkowe powiązanie między Text właściwością i TextBoxUserName właściwością w kodzie. Oznacza to, że za każdym razem, gdy użytkownik wprowadza tekst (i przenosi fokus poza TextBox), UserName właściwość w kodzie ulegnie zmianie. TextBoxPonadto tekst "będzie ustawiony na wartość przechowywaną we UserName właściwości podczas uruchamiania aplikacji lub za każdym razem, gdy zgłaszamy NotifyPropertyChanged zdarzenie za pomocą parametru propertyName"UserName". (W tej lekcji tego nie zrobimy).

Uwaga

W WPF tryb powiązania jest automatycznie określany dla najbardziej typowych sytuacji. Jeśli na przykład powiązanie Text z właściwością TextBoxklasy , WPF domyślnie ustawia tryb powiązania na TwoWay wartość . Oznacza to, że moglibyśmy nawet pominąć określanie trybu powiązania w tym miejscu i może właśnie napisać Text={Binding UserName}. Dowiedz się więcej o trybach powiązań tutaj.

4. Utwórz procedurę obsługi kliknięcia przycisku Prześlij

Następnie na powierzchni projektowej kliknij dwukrotnie przycisk Prześlij . Spowoduje to automatyczne utworzenie zdarzenia i Button_ClickMainWindow.xaml.cs otwarcie pliku. Button_Click nie jest bardzo opisową nazwą, więc zmień nazwę metody na OnSubmitClicked. Po zakończeniu wpisywania kliknij wskazówkę śrubokręta obok OnSubmitClicked linii, a następnie wybierz pozycję Zmień nazwę "Button_Clicked" na "OnSubmitClicked" z menu. Wróć do kodu XAML i sprawdź, czy kod XAML przycisku wygląda teraz następująco:

<Button Margin="10" 
        VerticalAlignment="Center" 
        Click="OnSubmitClicked">Submit</Button>

Wróćmy do kodu z tyłu, wyświetlimy proste okno dialogowe po naciśnięciu przycisku. Dodaj właściwość wygody do góry MainWindow klasy, która umożliwia nam łatwy dostęp do MainWindowDataContext obiektu ustawionego jako DataContext całego MainWindowobiektu .

private MainWindowDataContext DC => (MainWindowDataContext)DataContext;

Następnie dodaj następujący kod do OnSubmitClicked metody :

MessageBox.Show($"Hello {DC.UserName}!");

Wartość tekstu wprowadzonego w obiekcie TextBox jest przechowywana we MainWindowDataContext.UserName właściwości . Pierwszy wiersz przechowuje odwołanie do MainWindowDataContext obiektu w zmiennej tymczasowej. Drugi wiersz wyświetla pole komunikatu z powitaniem.

Jeśli nie znasz $"Hello {Username}" składni, jest to odpowiednik "Hello " + UserName + "!" elementu lub String.Format("Hello {0}!", UserName). Ta bardziej zwięzła i czytelna składnia jest nazywana interpolacją ciągów i została wprowadzona w języku C# 6.

5. Uruchamianie aplikacji

Przetestujmy to, co zrobiliśmy do tej pory! Uruchom aplikację, naciskając klawisz F5 lub Ctrl+F5. Wprowadź swoją nazwę, wybierz przycisk Prześlij , a okno dialogowe powinno Cię powitać.

Screenshot of sample app with new greeting dialog box that displays

6. Zaimplementuj IsNameNeeded właściwość

Zwróć uwagę, że część wpisu nazwy interfejsu użytkownika jest nadal wyświetlana po naciśnięciu przycisku Prześlij. Musimy ukryć formularz po pomyślnym wypełnieniu. Zróbmy to w następnym kroku przy użyciu powiązania danych.

Najpierw otwórz plik MainWindowDataContext.cs i wykonaj MainWindowDataContext dziedziczenie z INotifyPropertyChangedklasy , podobnie jak w przypadku Clock klasy .

using System.ComponentModel;

public class MainWindowDataContext : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

Następnie utwórz właściwość, aby wskazać, czy wprowadzanie nazwy użytkownika jest nadal potrzebne. Dodaj następujący kod w MainWindowDataContext klasie:

private bool _isNameNeeded = true;

public bool IsNameNeeded
{
    get { return _isNameNeeded; }
    set
    {
        if (value != _isNameNeeded)
        {
            _isNameNeeded = value;
            PropertyChanged?.Invoke(
                this, new PropertyChangedEventArgs(nameof(IsNameNeeded)));
        }
    }
}

Jest to dość standardowa właściwość logiczna z polem zapasowym i wartością truedomyślną , dopóki nie zostanie wyświetlony zestaw. Ustawiająca właściwość najpierw sprawdza, czy nowa wartość jest taka sama jak stara. Jeśli tak jest, nie ma potrzeby nic robić. Jeśli nic się nie zmieniło, nie chcesz rozpoczynać długiego procesu ponownego obliczania układu i ponownego renderowania kontrolek. Jeśli jednak wartość właściwości uległa zmianie, musisz poinformować interfejs użytkownika o tym przy użyciu PropertyChanged zdarzenia.

W poprzednim kodzie można zobaczyć standardowy wzorzec interfejsu INotifyPropertyChanged :

  • Sprawdź, czy wartość została zmieniona.
  • Jeśli tak, ustaw nową wartość.
  • Powiadom interfejs użytkownika.

Po powiadomieniu interfejsu użytkownika (przy założeniu, że tryb powiązania jest ustawiony na OneWay lub TwoWay), wywołuje metodę getter właściwości, otrzymuje nową wartość i odpowiednio zmienia interfejs użytkownika.

7. Ukryj formularz po wybraniu przycisku Prześlij

W naszym przypadku chcemy, aby formularz wprowadzania nazwy był widoczny tylko do momentu wybrania przycisku Prześlij . Następnie powinien zniknąć w tym samym czasie, gdy zostanie wyświetlony komunikat powitania. Zmieńmy metodę OnSubmitClicked , dodając ten kod na początku:

if (string.IsNullOrWhiteSpace(DC.UserName))
{
    return;
}

DC.IsNameNeeded = false;

Najpierw wykonywane jest szybkie sprawdzanie, ponieważ nie akceptujemy tutaj pustej nazwy użytkownika. Po wprowadzeniu IsNameNeeded nazwy jest ustawiona wartość false, a aplikacja kontynuuje wyświetlanie okna dialogowego komunikatu. Ustawienie wartości wywołania IsNameNeededNotifyPropertyChanged zdarzenia i powiadomienie interfejsu użytkownika.

Teraz skończymy z kodem, aby ukryć interfejs użytkownika. Wróćmy do kodu XAML!

Po stronie XAML musimy ukryć TextBlockwartość , , TextBoxi Button , gdy IsNameNeeded ma wartość false. Możemy też ukryć kontener , StackPanelw jednym kroku. Visibility Dodaj atrybut do StackPanelelementu , w następujący sposób:

Visibility="{Binding IsNameNeeded, Converter={StaticResource BooleanToVisibilityConverter}}"

To powiązanie składa się z dwóch części. Pierwsza część określa ścieżkę powiązania, która wskazuje IsNameNeeded właściwość MainWindowDataContext obiektu ustawionego jako DataContext cały Windowelement .

IsNameNeeded Ale właściwość jest wartością logiczną, natomiast Visibility jest typu System.Windows.Visibility, czyli enum. Musimy wykonać konwersję między nimi. Ta konwersja jest tak powszechna, WPF ma wbudowaną klasę pomocnika o nazwie BooleanToVisibilityConverter. Musimy utworzyć wystąpienie tej klasy i odwołać się do niego z deklaracji powiązania.

Tworzymy wystąpienie tej klasy w języku XAML jako zasób Window obiektu. Każda FrameworkElement może mieć własną kolekcję zasobów z kluczem identyfikującym każdy zasób w kolekcji. W BooleanToVisibilityConverter poprzednim powiązaniu jest to klucz wskazujący BooleanToVisibilityConverter obiekt wewnątrz kolekcji zasobów. Kolekcję zasobów można zdefiniować, dodając następujący kod do Windowelementu bezpośrednio po tagu otwierającym:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>

Uruchom aplikację, wprowadź swoją nazwę w pliku TextBoxi sprawdź, czy formularz wpisu rzeczywiście zniknie po wybraniu przycisku Prześlij .

8. Użyj powiązania interfejsu użytkownika do interfejsu użytkownika, aby wyświetlić powitanie

Zastąpmy element MessageDialog bardziej trwałym wyświetlaniem: a TextBlock w lewym górnym rogu. Dodaj nowy TextBlock element do głównej Grid kontrolki w języku XAML.

<TextBlock Text="{Binding Text, ElementName=tbName, StringFormat='Hello {0}!'}"
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

W tym nowym pliku TextBlockwprowadzono kilka nowych elementów. Odcięmy powiązanie atrybutu Text !

Aby ocenić wartość Text właściwości w TextBlockobiekcie , system wywołuje wbudowaną metodę String.Format z ciągiem "Hello {0}"formatu . Obiekt do formatowania będzie tbName.Text (innymi słowy, Text właściwość kontrolki tbName ). Tryb powiązania jest definiowany automatycznie jako OneWay, co oznacza, że TextBlock dane będą odbierane z TextBoxwłaściwości .s Text .

Jest to nazywane powiązaniem interfejsu użytkownika-interfejsu użytkownika, ponieważ zarówno źródło powiązania danych, jak i element docelowy znajdują się w interfejsie użytkownika. Aby zobaczyć ją w akcji, wystarczy uruchomić aplikację. Zwróć uwagę, jak powitanie jest aktualizowane przy użyciu każdej platformy keypress. Nie musisz nawet usuwać fokusu z TextBox przycisku Lub wybierać przycisk Prześlij .

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

W rzeczywistej aplikacji wyświetlanie nazwy użytkownika nie będzie odbywać się za pomocą powiązania interfejsu użytkownika-interfejsu użytkownika. Prawdopodobnie powiązalibyśsz się z DisplayName właściwością User klasy lub inną podobną metodą.

9. Ukryj powitanie do momentu wybrania opcji Prześlij

Tak fajnie, jak wygląda na to, że aktualizacja powitania podczas wpisywania: "Hello!" tekst podczas uruchamiania może być wyświetlany jako nieprofesjonalny. Najlepiej byłoby, aby powitanie TextBlock było niewidoczne do momentu wybrania przycisku Prześlij .

Aby obliczyć, czy powitanie jest widoczne, użyj właściwości o nazwie GreetingVisibilityi dodaj ją do MainWindowDataContext klasy.

public Visibility GreetingVisibility => IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;

Należy również dodać System.Windows przestrzeń nazw do usingelementu .MainWindowDataContext

Możesz pamiętać, że wcześniej, gdy ukrywaliśmy StackPanelelement , wiązaliśmy wartość z Visibility właściwością bool (która ma typ System.Windows.Visibility). Możemy jednak pominąć BooleanToVisibilityConverter , czy źródło powiązania jest już prawidłowym typem danych.

Tak jak poprzednio, musimy użyć PropertyChanged zdarzenia, aby powiadomić interfejs użytkownika, gdy chcemy, aby ponownie ocenić element GreetingVisibility. Dodajmy więc ten wiersz na końcu if bloku w IsNameNeeded ustawieniu.

PropertyChanged?.Invoke(
    this, new PropertyChangedEventArgs(nameof(GreetingVisibility)));

Gwarantuje to, że za każdym razem, gdy IsNameNeeded zostanie zmienione, zostaną zgłoszone dwa PropertyChanged zdarzenia: jedno dla samej właściwości i jedno dla IsNameNeeded właściwości obliczeniowej GreetingVisibility, która zależy od IsNameNeeded.

W ostatnim kroku wykonaj powiązanie, dodając Visibility atrybut do powitania TextBlock. W MainWindow.xamlpliku zmodyfikuj element TextBlock tak, aby wyglądał następująco:

<TextBlock Text="{Binding Text, ElementName=tbName, StringFormat='Hello {0}!'}"
           Visibility="{Binding GreetingVisibility}"
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

Na koniec, aby zatrzymać wyświetlanie MessageBoxelementu , oznacz następujący wiersz w metodzie OnSubmitClicked w pliku MainWindow.xaml.cs.

// MessageBox.Show($"Hello {DC.UserName}!");

Teraz możesz uruchomić aplikację i cieszyć się swoimi wiadomościami powitania.

Podsumowanie

W tej lekcji pokazano, jak powiązanie danych ułatwia transfer danych między interfejsem użytkownika a kodem lub między dwoma elementami interfejsu użytkownika. Jednak istnieje wiele kodu do zapisania, zwłaszcza podczas wywoływania PropertyChanged zdarzenia w zestawerach właściwości. W następnej lekcji utworzysz klasę pomocnika, aby uprościć korzystanie ze INotifyPropertyChanged wzorca.