Część 1. Część 1. Wprowadzenie do języka XAML
Xamarin.Forms W aplikacji język XAML jest najczęściej używany do definiowania zawartości wizualnej strony i współpracuje z plikiem kodu w języku C#.
Plik związany z kodem zapewnia obsługę kodu dla znaczników. Te dwa pliki współtworzyją nową definicję klasy, która obejmuje widoki podrzędne i inicjowanie właściwości. W pliku XAML klasy i właściwości odwołują się do elementów i atrybutów XML, a linki między znacznikami i kodem są ustanawiane.
Tworzenie rozwiązania
Aby rozpocząć edytowanie pierwszego pliku XAML, użyj programu Visual Studio lub Visual Studio dla komputerów Mac, aby utworzyć nowe Xamarin.Forms rozwiązanie. (Wybierz kartę poniżej odpowiadającą twojemu środowisku).
W systemie Windows uruchom program Visual Studio 2019, a w oknie uruchamiania kliknij pozycję Utwórz nowy projekt, aby utworzyć nowy projekt :
W oknie Tworzenie nowego projektu wybierz pozycję Mobile na liście rozwijanej Typ projektu, wybierz szablon Aplikacja mobilna (Xamarin.Forms) i kliknij przycisk Dalej:
W oknie Konfigurowanie nowego projektu ustaw nazwę projektu na XamlSamples (lub cokolwiek innego), a następnie kliknij przycisk Utwórz.
W oknie dialogowym Nowa aplikacja międzyplatformowa kliknij pozycję Puste, a następnie kliknij przycisk OK:
W rozwiązaniu są tworzone cztery projekty: biblioteka XamlSamples .NET Standard, XamlSamples.Android, XamlSamples.iOS oraz rozwiązanie platforma uniwersalna systemu Windows XamlSamples.UWP.
Po utworzeniu rozwiązania XamlSamples możesz przetestować środowisko projektowe, wybierając różne projekty platform jako projekt startowy rozwiązania oraz kompilując i wdrażając prostą aplikację utworzoną przez szablon projektu na emulatorach telefonu lub na rzeczywistych urządzeniach.
Jeśli nie musisz pisać kodu specyficznego dla platformy, udostępniony projekt biblioteki XamlSamples platformy .NET Standard to miejsce, w którym będziesz spędzać praktycznie cały czas programowania. Te artykuły nie będą ryzykować poza tym projektem.
Anatomia pliku XAML
W bibliotece XamlSamples platformy .NET Standard znajdują się pary plików o następujących nazwach:
- App.xaml, plik XAML; i
- App.xaml.cs plik kodu w języku C# skojarzony z plikiem XAML.
Musisz kliknąć strzałkę obok pliku App.xaml , aby wyświetlić plik za kodem.
Zarówno App.xaml , jak i App.xaml.cs współtworzyć klasę o nazwie App
, która pochodzi z Application
klasy . Większość innych klas z plikami XAML współtworzy klasę pochodzącą z ContentPage
klasy ; te pliki używają języka XAML do definiowania zawartości wizualnej całej strony. Dotyczy to dwóch pozostałych plików w projekcie XamlSamples :
- MainPage.xaml, plik XAML; i
- MainPage.xaml.cs pliku kodu w języku C#.
Plik MainPage.xaml wygląda następująco (chociaż formatowanie może być nieco inne):
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
x:Class="XamlSamples.MainPage">
<StackLayout>
<!-- Place new controls here -->
<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
Dwie deklaracje przestrzeni nazw XML (xmlns
) odnoszą się do identyfikatorów URI, pierwszy pozornie w witrynie internetowej platformy Xamarin, a drugi w witrynie firmy Microsoft. Nie przejmuj się sprawdzaniem, na co wskazują te identyfikatory URI. Nie ma tam nic. Są to po prostu identyfikatory URI należące do platformY Xamarin i firmy Microsoft, które zasadniczo działają jako identyfikatory wersji.
Pierwsza deklaracja przestrzeni nazw XML oznacza, że tagi zdefiniowane w pliku XAML bez prefiksu odwołują się do klas w pliku Xamarin.Forms, na przykład ContentPage
. Druga deklaracja przestrzeni nazw definiuje prefiks .x
Jest to używane w przypadku kilku elementów i atrybutów, które są wewnętrzne dla samego języka XAML i które są obsługiwane przez inne implementacje języka XAML. Jednak te elementy i atrybuty różnią się nieco w zależności od roku osadzonego w identyfikatorze URI. Xamarin.Forms obsługuje specyfikację XAML 2009, ale nie wszystkie.
Deklaracja local
przestrzeni nazw umożliwia dostęp do innych klas z projektu biblioteki .NET Standard.
Na końcu tego pierwszego tagu x
prefiks jest używany dla atrybutu o nazwie Class
. Ponieważ użycie tego x
prefiksu jest praktycznie uniwersalne dla przestrzeni nazw XAML, atrybuty XAML, takie jak Class
są prawie zawsze określane jako x:Class
.
Atrybut x:Class
określa w pełni kwalifikowaną nazwę klasy .NET: klasę MainPage
XamlSamples
w przestrzeni nazw. Oznacza to, że ten plik XAML definiuje nową klasę o nazwie MainPage
w XamlSamples
przestrzeni nazw pochodzącej z ContentPage
— tagu x:Class
, w którym pojawia się atrybut.
Atrybut x:Class
może być wyświetlany tylko w elemecie głównym pliku XAML w celu zdefiniowania pochodnej klasy języka C#. Jest to jedyna nowa klasa zdefiniowana w pliku XAML. Wszystkie inne elementy wyświetlane w pliku XAML są po prostu tworzone z istniejących klas i inicjowane.
Plik MainPage.xaml.cs wygląda następująco (oprócz nieużywanych using
dyrektyw):
using Xamarin.Forms;
namespace XamlSamples
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
}
Klasa MainPage
pochodzi z ContentPage
klasy , ale zwróć uwagę na definicję partial
klasy. Sugeruje to, że powinna istnieć inna definicja klasy częściowej dla MainPage
klasy , ale gdzie jest? A co to jest ta InitializeComponent
metoda?
Gdy program Visual Studio skompiluje projekt, analizuje plik XAML w celu wygenerowania pliku kodu C#. Jeśli spojrzysz na katalog XamlSamples\XamlSamples\obj\Debug , znajdziesz plik o nazwie XamlSamples.MainPage.xaml.g.cs. 'g' oznacza wygenerowany. Jest to druga częściowa definicja MainPage
klasy, która zawiera definicję InitializeComponent
metody wywoływanej z konstruktora MainPage
. Te dwie częściowe MainPage
definicje klas można następnie skompilować razem. W zależności od tego, czy kod XAML jest kompilowany, czy nie, plik XAML lub postać binarna pliku XAML jest osadzona w pliku wykonywalnym.
W czasie wykonywania kod w konkretnym projekcie platformy wywołuje metodę LoadApplication
, przekazując do niej nowe wystąpienie App
klasy w bibliotece .NET Standard. Konstruktor App
klasy tworzy wystąpienie MainPage
klasy . Konstruktor tej klasy wywołuje InitializeComponent
metodę , która następnie wywołuje LoadFromXaml
metodę, która wyodrębnia plik XAML (lub skompilowany plik binarny) z biblioteki .NET Standard. LoadFromXaml
Inicjuje wszystkie obiekty zdefiniowane w pliku XAML, łączy je wszystkie razem w relacjach nadrzędny-podrzędny, dołącza programy obsługi zdarzeń zdefiniowane w kodzie do zdarzeń ustawionych w pliku XAML i ustawia wynikowe drzewo obiektów jako zawartość strony.
Chociaż zwykle nie trzeba poświęcać dużo czasu na wygenerowane pliki kodu, czasami wyjątki środowiska uruchomieniowego są wywoływane w kodzie w wygenerowanych plikach, więc należy zapoznać się z nimi.
Podczas kompilowania i uruchamiania tego programu Label
element pojawia się w środku strony, co sugeruje kod XAML:
Aby uzyskać bardziej interesujące wizualizacje, wszystko, czego potrzebujesz, to bardziej interesujące XAML.
Dodawanie nowych stron XAML
Aby dodać inne klasy oparte na ContentPage
języku XAML do projektu, wybierz projekt biblioteki XamlSamples platformy .NET Standard, kliknij prawym przyciskiem myszy i wybierz polecenie Dodaj > nowy element.... W oknie dialogowym Dodawanie nowego elementu wybierz pozycję Strona zawartości elementów >>Xamarin.Formsvisual C# (nie strona zawartości (C#), która tworzy stronę tylko do kodu lub Widok zawartości, który nie jest stroną. Nadaj stronie nazwę, na przykład HelloXamlPage:
Dwa pliki są dodawane do projektu, HelloXamlPage.xaml i plik za kodem HelloXamlPage.xaml.cs.
Ustawianie zawartości strony
Zmodyfikuj plik HelloXamlPage.xaml, aby jedynymi tagami były te dla ContentPage
i :ContentPage.Content
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
Tagi ContentPage.Content
są częścią unikatowej składni języka XAML. Na początku mogą wydawać się nieprawidłowe xml, ale są one legalne. Kropka nie jest znakiem specjalnym w formacie XML.
Tagi ContentPage.Content
są nazywane tagami elementów właściwości. Content
jest właściwością ContentPage
, a zazwyczaj jest ustawiona na pojedynczy widok lub układ z widokami podrzędnymi. Zwykle właściwości stają się atrybutami w języku XAML, ale trudno byłoby ustawić Content
atrybut na obiekt złożony. Z tego powodu właściwość jest wyrażana jako element XML składający się z nazwy klasy i nazwy właściwości oddzielonej kropką. Content
Teraz właściwość można ustawić między tagami ContentPage.Content
w następujący sposób:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage"
Title="Hello XAML Page">
<ContentPage.Content>
<Label Text="Hello, XAML!"
VerticalOptions="Center"
HorizontalTextAlignment="Center"
Rotation="-15"
IsVisible="true"
FontSize="Large"
FontAttributes="Bold"
TextColor="Blue" />
</ContentPage.Content>
</ContentPage>
Zwróć również uwagę, że Title
atrybut został ustawiony na tagu głównym.
W tej chwili relacja między klasami, właściwościami i kodem XML powinna być widoczna: Xamarin.Forms klasa (taka jak ContentPage
lub Label
) pojawia się w pliku XAML jako element XML. Właściwości tej klasy — w tym Title
właściwości na ContentPage
i siedmiu — Label
zwykle są wyświetlane jako atrybuty XML.
Istnieje wiele skrótów, aby ustawić wartości tych właściwości. Niektóre właściwości są podstawowymi typami danych: na przykład właściwości i Text
są typu , Rotation
jest typu String
Double
, i IsVisible
(domyślnie true
i jest ustawiane tylko dla ilustracji) jest typu Boolean
.Title
Właściwość HorizontalTextAlignment
jest typu TextAlignment
, który jest wyliczeniem. W przypadku właściwości dowolnego typu wyliczenia wystarczy podać nazwę elementu członkowskiego.
Jednak w przypadku właściwości bardziej złożonych typów konwertery są używane do analizowania kodu XAML. Są to klasy, które Xamarin.Forms pochodzą z klasy TypeConverter
. Wiele z nich to klasy publiczne, ale niektóre nie. W przypadku tego konkretnego pliku XAML kilka z tych klas odgrywa rolę w tle:
LayoutOptionsConverter
VerticalOptions
dla właściwościFontSizeConverter
FontSize
dla właściwościColorTypeConverter
TextColor
dla właściwości
Te konwertery określają dozwoloną składnię ustawień właściwości.
Może ThicknessTypeConverter
obsłużyć jedną, dwie lub cztery liczby oddzielone przecinkami. Jeśli podano jedną liczbę, ma zastosowanie do wszystkich czterech stron. Z dwoma liczbami pierwszy jest w lewym i prawym dopełnieniu, a drugi jest górny i dolny. Cztery liczby są w kolejności lewej, górnej, prawej i dolnej.
Obiekt LayoutOptionsConverter
może przekonwertować nazwy publicznych pól LayoutOptions
statycznych struktury na wartości typu LayoutOptions
.
Może FontSizeConverter
obsługiwać element członkowski NamedSize
lub rozmiar czcionki liczbowej.
Obiekt ColorTypeConverter
akceptuje nazwy publicznych pól Color
statycznych struktury lub wartości szesnastkowe RGB z kanałem alfa lub bez niego poprzedzone znakiem numeru (#). Oto składnia bez kanału alfa:
TextColor="#rrggbb"
Każda z małych liter jest cyfrą szesnastkową. Poniżej przedstawiono sposób dołączania kanału alfa:
TextColor="#aarrggbb">
W przypadku kanału alfa należy pamiętać, że FF jest w pełni nieprzezroczyste, a 00 jest w pełni przezroczyste.
Dwa inne formaty umożliwiają określenie tylko jednej cyfry szesnastkowej dla każdego kanału:
TextColor="#rgb"
TextColor="#argb"
W takich przypadkach cyfra jest powtarzana w celu utworzenia wartości. Na przykład #CF3 jest kolorem RGB CC-FF-33.
Nawigacja między stronami
Po uruchomieniu programu MainPage
XamlSamples zostanie wyświetlony element . Aby wyświetlić nowe HelloXamlPage
, możesz ustawić to jako nową stronę uruchamiania w pliku App.xaml.cs lub przejść do nowej strony z witryny MainPage
.
Aby zaimplementować nawigację, najpierw zmień kod w konstruktorze App.xaml.cs , NavigationPage
aby obiekt został utworzony:
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
W konstruktorze MainPage.xaml.cs można utworzyć prosty Button
program obsługi zdarzeń i użyć go do przejścia do HelloXamlPage
elementu :
public MainPage()
{
InitializeComponent();
Button button = new Button
{
Text = "Navigate!",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
button.Clicked += async (sender, args) =>
{
await Navigation.PushAsync(new HelloXamlPage());
};
Content = button;
}
Content
Ustawienie właściwości strony zastępuje ustawienie Content
właściwości w pliku XAML. Po skompilowaniu i wdrożeniu nowej wersji tego programu zostanie wyświetlony przycisk na ekranie. Naciśnięcie powoduje przejście do .HelloXamlPage
Oto wynikowa strona na telefonach iPhone, Android i UWP:
Możesz wrócić do MainPage
korzystania z < przycisku Wstecz w systemie iOS, używając strzałki w lewo w górnej części strony lub w dolnej części telefonu w systemie Android lub przy użyciu strzałki w lewo w górnej części strony w systemie Windows 10.
Możesz eksperymentować z językiem XAML na różne sposoby renderowania elementu Label
. Jeśli musisz osadzić znaki Unicode w tekście, możesz użyć standardowej składni XML. Aby na przykład umieścić powitanie w inteligentnych cudzysłowach, użyj:
<Label Text="“Hello, XAML!”" … />
Oto jak wygląda:
Interakcje xAML i kodu
Przykład HelloXamlPage zawiera tylko jeden Label
element na stronie, ale jest to bardzo nietypowe. Większość ContentPage
pochodnych ustawia Content
właściwość na układ pewnego rodzaju, taki jak StackLayout
. Właściwość Children
obiektu StackLayout
jest zdefiniowana jako typ IList<View>
, ale w rzeczywistości jest obiektem typu ElementCollection<View>
, a kolekcja może być wypełniona wieloma widokami lub innymi układami. W języku XAML te relacje nadrzędny-podrzędny są ustanawiane z normalną hierarchią XML. Oto plik XAML nowej strony o nazwie XamlPlusCodePage:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="CenterAndExpand" />
<Label Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click Me!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Ten plik XAML jest syntaktycznie kompletny i wygląda następująco:
Można jednak rozważyć, że ten program będzie funkcjonalnie niedociągliwy. Slider
Być może element ma spowodować Label
wyświetlenie bieżącej wartości, a Button
element prawdopodobnie ma zrobić coś w programie.
Jak zobaczysz w części 4. Podstawy powiązań danych— zadanie wyświetlania Slider
wartości przy użyciu elementu Label
można obsłużyć w całości w języku XAML za pomocą powiązania danych. Warto jednak najpierw zobaczyć rozwiązanie kodu. Mimo to obsługa Button
kliknięcia zdecydowanie wymaga kodu. Oznacza to, że plik związany z kodem musi XamlPlusCodePage
zawierać programy obsługi dla ValueChanged
zdarzenia Slider
i Clicked
zdarzenia Button
. Dodajmy je:
namespace XamlSamples
{
public partial class XamlPlusCodePage
{
public XamlPlusCodePage()
{
InitializeComponent();
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
}
void OnButtonClicked(object sender, EventArgs args)
{
}
}
}
Te programy obsługi zdarzeń nie muszą być publiczne.
W pliku Slider
XAML tagi i Button
muszą zawierać atrybuty dla ValueChanged
zdarzeń i Clicked
odwołujących się do tych procedur obsługi:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="CenterAndExpand"
ValueChanged="OnSliderValueChanged" />
<Label Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button Text="Click Me!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Clicked="OnButtonClicked" />
</StackLayout>
</ContentPage>
Zwróć uwagę, że przypisanie procedury obsługi do zdarzenia ma taką samą składnię, jak przypisanie wartości do właściwości.
Jeśli procedura obsługi zdarzenia ValueChanged
Slider
będzie używać Label
elementu , aby wyświetlić bieżącą wartość, program obsługi musi odwoływać się do tego obiektu z kodu. Wymaga Label
nazwy, która jest określona z atrybutem x:Name
.
<Label x:Name="valueLabel"
Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
Prefiks x
atrybutu x:Name
wskazuje, że ten atrybut jest wewnętrzny dla języka XAML.
Nazwa przypisana do atrybutu x:Name
ma te same reguły co nazwy zmiennych języka C#. Na przykład musi zaczynać się od litery lub podkreślenia i nie zawierać osadzonych spacji.
Teraz program obsługi zdarzeń ValueChanged
może ustawić Label
wartość , aby wyświetlić nową Slider
wartość. Nowa wartość jest dostępna z argumentów zdarzeń:
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = args.NewValue.ToString("F3");
}
Lub program obsługi może uzyskać Slider
obiekt, który generuje to zdarzenie z argumentu sender
i uzyskać Value
właściwość z tego:
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}
Po pierwszym uruchomieniu programu wartość nie jest wyświetlanaSlider
, Label
ponieważ ValueChanged
zdarzenie nie zostało jeszcze wyzwolone. Ale każda manipulacja Slider
przyczyną wyświetlania wartości:
Teraz dla elementu Button
. Symulujemy odpowiedź na Clicked
zdarzenie, wyświetlając alert za pomocą Text
przycisku . Procedura obsługi zdarzeń może bezpiecznie rzutować sender
argument na element , Button
a następnie uzyskać dostęp do jego właściwości:
async void OnButtonClicked(object sender, EventArgs args)
{
Button button = (Button)sender;
await DisplayAlert("Clicked!",
"The button labeled '" + button.Text + "' has been clicked",
"OK");
}
Metoda jest definiowana jako async
, ponieważ DisplayAlert
metoda jest asynchroniczna i powinna być poprzedzona operatorem await
, który zwraca wartość po zakończeniu metody. Ponieważ ta metoda uzyskuje Button
wyzwalanie zdarzenia z argumentu sender
, można użyć tej samej procedury obsługi dla wielu przycisków.
Wiesz już, że obiekt zdefiniowany w języku XAML może wyzwalać zdarzenie obsługiwane w pliku za pomocą kodu i że plik za pomocą kodu może uzyskać dostęp do obiektu zdefiniowanego w języku XAML przy użyciu przypisanej do niego nazwy z atrybutem x:Name
. Są to dwa podstawowe sposoby interakcji kodu i XAML.
Dodatkowe szczegółowe informacje na temat działania języka XAML można uzyskać, sprawdzając nowo wygenerowany plik XamlPlusCode.xaml.g.cs, który zawiera teraz dowolną nazwę przypisaną do dowolnego x:Name
atrybutu jako pola prywatnego. Oto uproszczona wersja tego pliku:
public partial class XamlPlusCodePage : ContentPage {
private Label valueLabel;
private void InitializeComponent() {
this.LoadFromXaml(typeof(XamlPlusCodePage));
valueLabel = this.FindByName<Label>("valueLabel");
}
}
Deklaracja tego pola umożliwia swobodne używanie zmiennej w dowolnym miejscu w pliku klasy częściowej XamlPlusCodePage
w ramach jurysdykcji. W czasie wykonywania pole jest przypisywane po przeanalizowaniu kodu XAML. Oznacza to, że pole jest null
wtedy, valueLabel
gdy XamlPlusCodePage
konstruktor zaczyna się, ale jest prawidłowy po InitializeComponent
wywołaniu.
Po InitializeComponent
powrocie kontrolki z powrotem do konstruktora wizualizacje strony zostały skonstruowane tak, jakby zostały utworzone i zainicjowane w kodzie. Plik XAML nie odgrywa już żadnej roli w klasie. Możesz manipulować tymi obiektami na stronie w dowolny sposób, na przykład przez dodanie widoków do obiektu lub ustawienie Content
właściwości strony na StackLayout
coś innego całkowicie. Możesz "chodzić po drzewie", sprawdzając Content
właściwość strony i elementy w Children
kolekcjach układów. Właściwości widoków dostępnych w ten sposób można ustawić lub dynamicznie przypisywać do nich programy obsługi zdarzeń.
Zapraszam. Jest to strona, a kod XAML jest tylko narzędziem do kompilowania zawartości.
Podsumowanie
W tym wprowadzeniu pokazano, jak plik I plik kodu XAML współtworzy definicję klasy oraz sposób interakcji plików XAML i kodu. Jednak XAML ma również własne unikatowe funkcje składniowe, które pozwalają na ich używanie w bardzo elastyczny sposób. Możesz rozpocząć eksplorowanie ich w części 2. Podstawowa składnia XAML.