Porównanie interfejsu użytkownika opartego na zdarzeniach z interfejsem użytkownika powiązanego z danymi
- 6 min
Interfejs użytkownika oparty na zdarzeniach został zaprojektowany wokół zdarzeń ujawnianych przez kontrolkę. Te zdarzenia mogą być skojarzone z kodem 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 zdarzenia Clicked
może uruchomić operację, a następnie ustawić właściwość IsEnabled
przycisku na wartość false
, aby uniemożliwić 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, właściwość IsEnabled
jest powiązana z właściwością IsBusy
w obiekcie danych. Za każdym razem, gdy obiekt danych stanie się "zajęty", stan włączonego przycisku jest automatycznie zmieniany w celu dopasowania.
Zalety i wady używania zdarzeń i kodu-behind
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, pokazując wilgotność.
<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 procedura obsługi zdarzeń wysyła zapytanie do usługi pogodowej o najnowszą prognozę pogody, używając danych wprowadzonych w PostalCode
kontrolce wprowadzania, i ustawia tekst Humidity
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 tej jednej procedurze obsługi zdarzeń, trzy kontrolki są ściśle powiązane ze sobą i danymi za pośrednictwem zaplecza 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 XAML lub kodzie, ale są one znacznie bardziej powszechne w XAML, gdzie pomagają zmniejszyć rozmiar pliku code-behind. Gdy zastąpisz kod proceduralny w programach obsługi zdarzeń kodem deklaratywnym lub znacznikiem, aplikacja zostanie 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; Omówimy to 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
control: właściwość tej kontrolkiText
jest powiązana z właściwością o nazwieLocation
.Button
control: właściwość przyciskuCommand
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 wiązania danychClicked
.Label
control: TaText
właściwość jest powiązana z właściwością o nazwieHumidity
.
W tym prostym interfejsie użytkownika całe zaplecze kodu jest wyeliminowane. Usunięcie całego kodu zakulisowego nie jest celem powiązania danych, mimo że jest to możliwe. Code-behind nadal ma znaczenie. Ile powiązania danych implementujesz, jest do Ciebie.
Teraz interfejs użytkownika jest luźno powiązany z obiektem danych. Dlaczego jest luźno sprzężone zamiast ściśle sprzężone? Ze względu na sposób oceniania powiązań. Każda kontrolka ma właściwość BindingContext
. 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 martwienia się 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 automatycznie synchronizowany z danymi, a logika aplikacji jest oddzielona od interfejsu użytkownika.