Przesyłanie danych za pomocą powiązania danych
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.
Po wybraniu przycisku Prześlij aplikacja wyświetli proste powitanie u góry.
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 TextBox
i 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ę TextBox
Text
, 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 TextBlock
wł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. TextBox
Ponadto 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ć.
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ą true
domyś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 IsNameNeeded
NotifyPropertyChanged
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ć TextBlock
wartość , , TextBox
i Button
, gdy IsNameNeeded
ma wartość false. Możemy też ukryć kontener , StackPanel
w jednym kroku. Wystarczy dodać Visibility
atrybut do StackPanel
elementu , w następujący sposób:
Visibility="{x:Bind IsNameNeeded, Mode=OneWay}"
Uruchom aplikację, wprowadź swoją nazwę w pliku TextBox
i 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 TextBlock
obiekcie , 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 TextBox
wł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 .
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 GetGreetingVisibility
i dodaj ją do MainPage
klasy .
public Visibility GetGreetingVisibility()
{
return IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;
}
Można zauważyć, że podczas ukrywania StackPanel
elementu 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 MessageDialog
elementu , 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 DataContext
systemie .
Rozszerzmy istniejącą demonstrację z przyjaznym powitaniem, które wygląda następująco.
Po wybraniu przycisku Prześlij aplikacja wyświetli proste powitanie u góry.
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 MainWindowDataContext
i 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 Window
klasy . 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 DataContext
TextBlock
obiekcie .
2. Tworzenie interfejsu użytkownika wpisu danych
Interfejs użytkownika wprowadzania danych jest prosty: tylko element TextBlock
, a TextBox
i 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.cs
i utwórz nową właściwość o nazwie UserName
.
public string? UserName { get; set; }
Wróć do MainWindow.xaml
elementu , możemy utworzyć powiązanie danych między właściwością UserName
a kontrolką TextBox
. Zmień kontrolkę TextBox
Text
, 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 TextBlock
wł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 TextBox
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. TextBox
Ponadto 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ą TextBox
klasy , 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_Click
MainWindow.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 MainWindow
obiektu .
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ć.
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 INotifyPropertyChanged
klasy , 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ą true
domyś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 IsNameNeeded
NotifyPropertyChanged
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ć TextBlock
wartość , , TextBox
i Button
, gdy IsNameNeeded
ma wartość false. Możemy też ukryć kontener , StackPanel
w jednym kroku. Visibility
Dodaj atrybut do StackPanel
elementu , 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 Window
element .
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 Window
elementu bezpośrednio po tagu otwierającym:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>
Uruchom aplikację, wprowadź swoją nazwę w pliku TextBox
i 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 TextBlock
wprowadzono kilka nowych elementów. Odcięmy powiązanie atrybutu Text
!
Aby ocenić wartość Text
właściwości w TextBlock
obiekcie , 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 TextBox
wł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 .
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 GreetingVisibility
i dodaj ją do MainWindowDataContext
klasy.
public Visibility GreetingVisibility => IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;
Należy również dodać System.Windows
przestrzeń nazw do using
elementu .MainWindowDataContext
Możesz pamiętać, że wcześniej, gdy ukrywaliśmy StackPanel
element , 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.xaml
pliku 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 MessageBox
elementu , 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.