Porównanie interfejsu użytkownika opartego na zdarzeniach z interfejsem użytkownika powiązanego z danymi
Interfejs użytkownika oparty na zdarzeniach został zaprojektowany wokół zdarzeń ujawnianych przez kontrolkę. Te zdarzenia mogą być skojarzone z kodem procedury obsługi zdarzeń wywoływanym po wyzwoleniu zdarzenia. Załóżmy na przykład, że masz przycisk, który po kliknięciu wykonuje długotrwałą operację. Procedura obsługi zdarzeń przypisana do Clicked
zdarzenia może uruchomić operację, a następnie ustawić właściwość przycisku IsEnabled
na false
wartość , uniemożliwiając ponowne kliknięcie przycisku, gdy operacja jest uruchomiona.
Interfejs użytkownika powiązany z danymi używa powiązania danych do prezentowania danych i interakcji z nimi. Właściwości kontrolek są powiązane z właściwościami obiektu danych, a te powiązania mogą wykrywać zmiany we właściwościach. Korzystając z poprzedniego przykładu, rozważ przycisk, który wykonuje długotrwałą operację. Zamiast wyłączać przycisk w kodzie, IsEnabled
właściwość jest powiązana z właściwością obiektu IsBusy
danych. Za każdym razem, gdy obiekt danych stanie się "zajęty", stan włączony przycisku jest automatycznie zmieniany tak, aby był zgodny.
Zalety i wady używania zdarzeń i kodu za pomocą kodu
Używanie obsługi zdarzeń kontrolki z kodem za pomocą kodu jest szybkim i wygodnym sposobem projektowania logiki aplikacji dla interfejsu użytkownika. Kod służy do wywoływania usług w celu pobierania danych, wykonywania operacji na tych danych i interakcji z kontrolkami na stronie. Kod służy do synchronizowania interfejsu użytkownika i danych.
Rozważmy przykład aplikacji usługi pogodowej. Poniższy fragment XAML zawiera prosty przycisk interfejsu użytkownika, który użytkownik wybiera, aby pobrać najnowsze dane i zaktualizować interfejs użytkownika z wilgotnością.
<VerticalStackLayout Margin="10">
<HorizontalStackLayout Spacing="20">
<Label Text="Postal Code:" VerticalOptions="Center" />
<Entry x:Name="PostalCode" WidthRequest="100" />
<Button x:Name="RefreshWeatherButton" Text="Refresh" WidthRequest="200" Clicked="RefreshWeatherButton_Clicked" />
</HorizontalStackLayout>
<Label x:Name="Humidity" Text="Humidity: ?" />
</VerticalStackLayout>
W tym przykładzie istnieją trzy nazwane kontrolki:
Entry
kontrolka o nazwie PostalCode.Button
kontrolka o nazwie RefreshWeatherButton.Label
kontrolka o nazwie Wilgotność.
Element RefreshWeatherButton
ma program obsługi zdarzeń zadeklarowany dla Clicked
zdarzenia. Po kliknięciu przycisku program obsługi zdarzeń wysyła zapytanie do usługi pogodowej dla najnowszej prognozy pogody, używając danych wprowadzonych w PostalCode
kontrolce wprowadzania i ustawia Humidity
tekst etykiety na bieżącą wilgotność.
private void RefreshWeatherButton_Clicked(object sender, EventArgs e)
{
WeatherService.Location = PostalCode.Text;
WeatherService.Refresh();
Humidity.Text = $"Humidity: {WeatherService.Humidity}";
}
W tym jednym programie obsługi zdarzeń trzy kontrolki są ściśle powiązane ze sobą i dane za pośrednictwem kodu.
Ten projekt działa świetnie w przypadku małych interfejsów użytkownika, ale gdy tylko interfejs użytkownika stanie się złożony, utrzymanie ściśle powiązanego kodu może stać się kłopotliwe. Jeśli usuniesz lub zmienisz kontrolkę, musisz wyczyścić dowolny kod przy użyciu tych kontrolek interfejsu użytkownika, które mogą obejmować procedurę obsługi zdarzeń. Jeśli zdecydujesz się przeprojektować interfejs użytkownika, będziesz mieć wiele kodu do refaktoryzacji. A gdy struktura danych zapasowych ulegnie zmianie, musisz zagłębić się w kod każdego interfejsu użytkownika, aby zachować synchronizację.
Powiązanie danych pomaga
Powiązania danych można zaimplementować w języku XAML lub kodzie, ale są znacznie bardziej powszechne w języku XAML, gdzie pomagają zmniejszyć rozmiar pliku za pomocą kodu. Zastępując kod proceduralny w programach obsługi zdarzeń kodem deklaratywnym lub znacznikiem, aplikacja jest uproszczona i wyjaśniona. Ponieważ powiązania nie wymagają kodu, możesz łatwo utworzyć, zmienić lub przeprojektować interfejs użytkownika, aby dopasować go do sposobu prezentowania danych.
Przyjrzyjmy się takiemu przykładowi, jak w poprzedniej sekcji, ale zaktualizujmy go tak, aby używał powiązania danych:
<VerticalStackLayout Margin="10">
<HorizontalStackLayout Spacing="20">
<Label Text="Postal Code:" VerticalOptions="Center" />
<Entry Text="{Binding Location, Mode=OneWayToSource}" WidthRequest="100" />
<Button Text="Refresh" Command="{Binding RefreshWeather}" WidthRequest="200" />
</HorizontalStackLayout>
<Label Text="{Binding Humidity}" />
</VerticalStackLayout>
Właściwości, które są powiązane z danymi, używają składni {Binding ...}
rozszerzenia XAML dla wartości właściwości. Nie martw się jeszcze o szczegóły, które zostały omówione w dalszej części tego modułu.
Te same trzy kontrolki są deklarowane w języku XAML, ale żadna z nich nie jest nazwana, ponieważ nazwa nie jest wymagana:
Entry
kontrola:Ta właściwość kontrolki
Text
jest powiązana z właściwością o nazwieLocation
.Button
kontrola:Właściwość przycisku
Command
jest powiązana z właściwością o nazwieRefreshWeather
.Command
jest właściwością przycisku, który wywołuje kod po naciśnięciu przycisku. Jest to alternatywa dla zdarzenia używanego w powiązaniuClicked
danych.Label
kontrola:Ta
Text
właściwość jest powiązana z właściwością o nazwieHumidity
.
W tym prostym interfejsie użytkownika wszystkie elementy kodu są usuwane. Usunięcie całego kodu nie jest punktem powiązania danych, mimo że zwykle jest to możliwe. Kod-behind nadal ma swoje miejsce. Ile powiązania danych implementujesz, jest do Ciebie.
Teraz interfejs użytkownika jest luźno powiązany z obiektem danych. Dlaczego jest luźno powiązane zamiast ściśle powiązane? Ze względu na sposób oceniania powiązań. Każda kontrolka BindingContext
ma właściwość . Jeśli kontekst nie jest ustawiony, kontekst kontrolki nadrzędnej jest używany i tak dalej, dopóki nie zostanie obliczony katalog główny XAML. Podczas oceniania powiązań wystąpienie obiektu kontekstu jest sprawdzane pod kątem wymaganych właściwości, takich jak powiązanie kontrolki Text
etykiety z właściwością kontekstu Humidity
. Jeśli Humidity
nie istnieje w kontekście, nic się nie dzieje.
Ponieważ interfejs użytkownika jest luźno powiązany, możesz przeprojektować interfejs użytkownika bez obaw o niezgodność kodu. Można jednak przerwać funkcjonalność. Możesz na przykład usunąć przycisk, a aplikacja będzie nadal kompilowana i uruchamiana, ale nie masz możliwości odświeżenia pogody. Z drugiej strony można zastąpić kontrolki Entry
i Button
pojedynczą SearchBar
kontrolką . Ta kontrolka umożliwia wprowadzanie tekstu i wywoływanie polecenia.
<SearchBar Text="{Binding Location, Mode=OneWayToSource}" SearchCommand="{Binding RefreshWeather}" />
Jak widać, użycie powiązania danych w projekcie interfejsu użytkownika może pomóc w rozwoju i zmianie interfejsu użytkownika bez dużej ilości pracy. Dzięki temu interfejs użytkownika jest synchronizowany automatycznie z danymi, a logika aplikacji jest oddzielona od interfejsu użytkownika.