Xamarin.Forms Tryb powiązania
W poprzednim artykule alternatywne powiązania kodu i alternatywne powiązania XAML zawierały element Label
z właściwością Scale
powiązaną Value
z właściwością Slider
. Ponieważ początkowa Slider
wartość to 0, spowodowało Scale
to ustawienie właściwości Label
0, a nie 1, a Label
zniknęło.
Strona Powiązanie odwrotne jest podobna do programów w poprzednim artykule, z tą różnicą, że powiązanie danych jest definiowane na Slider
zamiast w pliku Label
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.ReverseBindingPage"
Title="Reverse Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
VerticalOptions="CenterAndExpand"
Value="{Binding Source={x:Reference label},
Path=Opacity}" />
</StackLayout>
</ContentPage>
Na początku może się to wydawać wstecz: teraz Label
jest to źródło powiązania danych, a Slider
element jest obiektem docelowym. Powiązanie odwołuje się do Opacity
właściwości Label
, która ma wartość domyślną 1.
Jak można się spodziewać, parametr Slider
jest inicjowany do wartości 1 z początkowej Opacity
Label
wartości . Jest to wyświetlane na zrzucie ekranu systemu iOS po lewej stronie:
Ale może być zaskoczony, że Slider
nadal działa, jak pokazuje zrzut ekranu systemu Android. Wydaje się, że powiązanie danych działa lepiej, gdy Slider
element docelowy powiązania jest elementem docelowym powiązania, a nie Label
dlatego, że inicjowanie działa tak, jak możemy się spodziewać.
Różnica między przykładem odwrotnego powiązania a wcześniejszymi przykładami obejmuje tryb powiązania.
Domyślny tryb powiązania
Tryb powiązania jest określony z elementem członkowskim BindingMode
wyliczenia:
Default
TwoWay
— dane idą w obie strony między źródłem a obiektem docelowymOneWay
— dane przechodzą ze źródła do miejsca docelowegoOneWayToSource
— dane przechodzą z miejsca docelowego do źródłaOneTime
— dane przechodzą ze źródła do miejsca docelowego, ale tylko wtedy, gdyBindingContext
zmiany (nowe z wersją Xamarin.Forms 3.0)
Każda właściwość powiązana ma domyślny tryb powiązania, który jest ustawiany podczas tworzenia właściwości możliwej do powiązania i która jest dostępna z DefaultBindingMode
właściwości BindableProperty
obiektu. Ten domyślny tryb powiązania wskazuje tryb obowiązujący, gdy ta właściwość jest obiektem docelowym powiązania danych.
Domyślny tryb powiązania dla większości właściwości, takich jak Rotation
, Scale
i Opacity
to OneWay
. Gdy te właściwości są obiektami docelowymi powiązania danych, właściwość docelowa jest ustawiana ze źródła.
Jednak domyślnym trybem powiązania dla Value
właściwości elementu Slider
jest TwoWay
. Oznacza to, że gdy Value
właściwość jest obiektem docelowym powiązania danych, element docelowy jest ustawiany ze źródła (jak zwykle), ale źródło jest również ustawione z obiektu docelowego. Umożliwia to ustawienie wartości Slider
początkowej Opacity
.
To powiązanie dwukierunkowe może wydawać się tworzenie nieskończonej pętli, ale tak się nie dzieje. Właściwości możliwe do powiązania nie sygnalizują zmiany właściwości, chyba że właściwość rzeczywiście ulegnie zmianie. Zapobiega to nieskończonej pętli.
Powiązania dwukierunkowe
Większość właściwości możliwych do powiązania ma domyślny tryb powiązania, OneWay
ale następujące właściwości mają domyślny tryb TwoWay
powiązania :
Date
właściwośćDatePicker
Text
Editor
właściwość , ,Entry
SearchBar
iEntryCell
IsRefreshing
właściwośćListView
SelectedItem
właściwośćMultiPage
SelectedIndex
właściwości iSelectedItem
Picker
Value
właściwość iSlider
Stepper
IsToggled
właściwośćSwitch
On
właściwośćSwitchCell
Time
właściwośćTimePicker
Te konkretne właściwości są definiowane jako TwoWay
bardzo dobry powód:
Gdy powiązania danych są używane z architekturą aplikacji Model-View-ViewModel (MVVM), klasa ViewModel jest źródłem powiązania danych, a widok, który składa się z widoków, takich jak Slider
, są obiektami docelowymi powiązania danych. Powiązania MVVM przypominają przykład Odwrotne powiązanie więcej niż powiązania w poprzednich przykładach. Bardzo prawdopodobne jest, że każdy widok na stronie ma zostać zainicjowany z wartością odpowiedniej właściwości w modelu ViewModel, ale zmiany w widoku powinny również mieć wpływ na właściwość ViewModel.
Właściwości z domyślnymi trybami TwoWay
powiązania to te właściwości, które najprawdopodobniej będą używane w scenariuszach MVVM.
Powiązania jednokierunkowe do źródła
Właściwości możliwe do powiązania tylko do odczytu mają domyślny tryb OneWayToSource
powiązania . Istnieje tylko jedna właściwość do odczytu/zapisu, która ma domyślny tryb OneWayToSource
powiązania :
SelectedItem
właściwośćListView
Uzasadnieniem jest to, że powiązanie właściwości SelectedItem
powinno spowodować ustawienie źródła powiązania. Przykład w dalszej części tego artykułu zastępuje to zachowanie.
Powiązania jednorazowe
Kilka właściwości ma domyślny tryb OneTime
powiązania , w tym IsTextPredictionEnabled
właściwość Entry
.
Właściwości docelowe z trybem OneTime
powiązania są aktualizowane tylko wtedy, gdy kontekst powiązania ulegnie zmianie. W przypadku powiązań dla tych właściwości docelowych upraszcza to infrastrukturę powiązania, ponieważ nie jest konieczne monitorowanie zmian we właściwościach źródłowych.
ViewModels and Property-Change Notifications
Na stronie Selektor kolorów prostych przedstawiono użycie prostego modelu ViewModel. Powiązania danych umożliwiają użytkownikowi wybranie koloru przy użyciu trzech Slider
elementów odcieni, nasycenia i jasności.
Model ViewModel jest źródłem powiązania danych. Model ViewModel nie definiuje właściwości możliwych do powiązania, ale implementuje mechanizm powiadomień, który umożliwia powiadamianie infrastruktury powiązania, gdy wartość właściwości ulegnie zmianie. Ten mechanizm powiadomień jest interfejsem INotifyPropertyChanged
, który definiuje jedno zdarzenie o nazwie PropertyChanged
. Klasa, która implementuje ten interfejs, zwykle uruchamia zdarzenie, gdy jedna z jego właściwości publicznych zmienia wartość. Zdarzenie nie musi być uruchamiane, jeśli właściwość nigdy się nie zmienia. (Interfejs INotifyPropertyChanged
jest również implementowany przez BindableObject
program i PropertyChanged
zdarzenie jest wyzwalane za każdym razem, gdy właściwość, którą można powiązać zmienia wartość).
Klasa HslColorViewModel
definiuje pięć właściwości: Hue
właściwości , Saturation
Luminosity
, i Color
są powiązane. Gdy którykolwiek z trzech składników kolorów zmienia wartość, Color
właściwość jest ponownie obliczana, a PropertyChanged
zdarzenia są wyzwalane dla wszystkich czterech właściwości:
public class HslColorViewModel : INotifyPropertyChanged
{
Color color;
string name;
public event PropertyChangedEventHandler PropertyChanged;
public double Hue
{
set
{
if (color.Hue != value)
{
Color = Color.FromHsla(value, color.Saturation, color.Luminosity);
}
}
get
{
return color.Hue;
}
}
public double Saturation
{
set
{
if (color.Saturation != value)
{
Color = Color.FromHsla(color.Hue, value, color.Luminosity);
}
}
get
{
return color.Saturation;
}
}
public double Luminosity
{
set
{
if (color.Luminosity != value)
{
Color = Color.FromHsla(color.Hue, color.Saturation, value);
}
}
get
{
return color.Luminosity;
}
}
public Color Color
{
set
{
if (color != value)
{
color = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Hue"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Saturation"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Luminosity"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
Name = NamedColor.GetNearestColorName(color);
}
}
get
{
return color;
}
}
public string Name
{
private set
{
if (name != value)
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
get
{
return name;
}
}
}
Color
Gdy właściwość ulegnie zmianie, metoda statyczna GetNearestColorName
w NamedColor
klasie (również uwzględniona w rozwiązaniu DataBindingDemos) uzyskuje najbliższy nazwany kolor i ustawia Name
właściwość. Ta Name
właściwość ma prywatną set
metodę dostępu, więc nie można jej ustawić spoza klasy.
Gdy model ViewModel jest ustawiony jako źródło powiązania, infrastruktura powiązania dołącza procedurę obsługi do PropertyChanged
zdarzenia. W ten sposób powiązanie może zostać powiadomione o zmianach właściwości, a następnie ustawić właściwości docelowe ze zmienionych wartości.
Jednak jeśli właściwość docelowa (lub Binding
definicja we właściwości docelowej) ma BindingMode
OneTime
wartość , nie jest konieczne, aby infrastruktura powiązania dołączała program obsługi w PropertyChanged
zdarzeniu. Właściwość docelowa jest aktualizowana tylko wtedy, gdy BindingContext
zmienia się, a nie wtedy, gdy sama właściwość źródłowa ulegnie zmianie.
Plik XAML selektora prostego koloru tworzy wystąpienie HslColorViewModel
w słowniku zasobów strony i inicjuje Color
właściwość. Właściwość BindingContext
Grid
właściwości jest ustawiona na StaticResource
rozszerzenie powiązania, aby odwoływać się do tego zasobu:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SimpleColorSelectorPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:HslColorViewModel x:Key="viewModel"
Color="MediumTurquoise" />
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid BindingContext="{StaticResource viewModel}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<BoxView Color="{Binding Color}"
Grid.Row="0" />
<StackLayout Grid.Row="1"
Margin="10, 0">
<Label Text="{Binding Name}"
HorizontalTextAlignment="Center" />
<Slider Value="{Binding Hue}" />
<Slider Value="{Binding Saturation}" />
<Slider Value="{Binding Luminosity}" />
</StackLayout>
</Grid>
</ContentPage>
Widoki BoxView
, Label
i trzy Slider
dziedziczą kontekst powiązania z klasy Grid
. Te widoki to wszystkie obiekty docelowe powiązania odwołujące się do właściwości źródła w modelu ViewModel. Color
Dla właściwości BoxView
, i Text
właściwości Label
, powiązania danych to OneWay
: Właściwości w widoku są ustawione z właściwości w Modelu Widok.
Właściwość Value
, jednak ma TwoWay
wartość Slider
. Umożliwia to ustawienie każdego Slider
elementu z modelu ViewModel, a także ustawienie modelu ViewModel z każdego Slider
elementu .
Po pierwszym uruchomieniu programu wszystkie BoxView
elementy , Label
i trzy Slider
elementy są ustawione z modelu ViewModel na podstawie początkowej Color
właściwości ustawionej podczas tworzenia wystąpienia modelu ViewModel. Jest to wyświetlane na zrzucie ekranu systemu iOS po lewej stronie:
W miarę manipulowania suwakami kontrolki BoxView
i Label
są odpowiednio aktualizowane, jak pokazano na zrzucie ekranu systemu Android.
Utworzenie wystąpienia modelu ViewModel w słowniku zasobów jest jednym z typowych podejść. Istnieje również możliwość utworzenia wystąpienia elementu ViewModel w tagach elementu właściwości dla BindingContext
właściwości. W pliku XAML selektora kolorów prostych spróbuj usunąć HslColorViewModel
element ze słownika zasobów i ustawić go na właściwość podobną do BindingContext
następującejGrid
:
<Grid>
<Grid.BindingContext>
<local:HslColorViewModel Color="MediumTurquoise" />
</Grid.BindingContext>
···
</Grid>
Kontekst powiązania można ustawić na różne sposoby. Czasami plik w tle tworzy wystąpienie elementu ViewModel i ustawia go na BindingContext
właściwość strony. Są to wszystkie prawidłowe podejścia.
Zastępowanie trybu powiązania
Jeśli domyślny tryb powiązania we właściwości docelowej nie jest odpowiedni dla określonego powiązania danych, można go zastąpić, ustawiając Mode
właściwość (lub Mode
właściwość Binding
Binding
rozszerzenia znaczników) na jeden z elementów członkowskich BindingMode
wyliczenia.
Jednak ustawienie Mode
właściwości na TwoWay
wartość nie zawsze działa zgodnie z oczekiwaniami. Na przykład spróbuj zmodyfikować alternatywny plik XAML powiązania XAML, aby uwzględnić TwoWay
go w definicji powiązania:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Path=Value,
Mode=TwoWay}" />
Może się spodziewać, że Slider
właściwość zostanie zainicjowana do początkowej Scale
wartości właściwości, czyli 1, ale tak się nie stanie. TwoWay
Po zainicjowaniu powiązania element docelowy jest ustawiany z pierwszego źródła, co oznacza, że Scale
właściwość jest ustawiona na wartość domyślną Slider
0. TwoWay
Gdy powiązanie jest ustawione na Slider
obiekcie , Slider
element jest początkowo ustawiany ze źródła.
Tryb powiązania można ustawić OneWayToSource
na w przykładzie Alternatywne powiązanie XAML:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Path=Value,
Mode=OneWayToSource}" />
Teraz parametr Slider
jest inicjowany na 1 (wartość Scale
domyślna ) ale manipulowanie Slider
właściwością nie ma wpływu na Scale
właściwość, więc nie jest to bardzo przydatne.
Uwaga
Klasa VisualElement
definiuje również właściwości ScaleX
i ScaleY
, które umożliwiają skalowanie klasy VisualElement
w różny sposób poziomo i pionowo.
Bardzo przydatna aplikacja zastępowania domyślnego trybu powiązania z TwoWay
właściwością SelectedItem
ListView
. Domyślnym trybem powiązania jest OneWayToSource
. Po ustawieniu powiązania danych we SelectedItem
właściwości w celu odwołania się do właściwości źródłowej w modelu ViewModel ta właściwość źródłowa jest ustawiana z zaznaczenia ListView
. Jednak w niektórych okolicznościach można również zainicjować element ListView
z modelu ViewModel.
Na stronie Przykładowe ustawienia przedstawiono tę technikę. Ta strona reprezentuje prostą implementację ustawień aplikacji, które są bardzo często zdefiniowane w modelu ViewModel, na przykład w tym SampleSettingsViewModel
pliku:
public class SampleSettingsViewModel : INotifyPropertyChanged
{
string name;
DateTime birthDate;
bool codesInCSharp;
double numberOfCopies;
NamedColor backgroundNamedColor;
public event PropertyChangedEventHandler PropertyChanged;
public SampleSettingsViewModel(IDictionary<string, object> dictionary)
{
Name = GetDictionaryEntry<string>(dictionary, "Name");
BirthDate = GetDictionaryEntry(dictionary, "BirthDate", new DateTime(1980, 1, 1));
CodesInCSharp = GetDictionaryEntry<bool>(dictionary, "CodesInCSharp");
NumberOfCopies = GetDictionaryEntry(dictionary, "NumberOfCopies", 1.0);
BackgroundNamedColor = NamedColor.Find(GetDictionaryEntry(dictionary, "BackgroundNamedColor", "White"));
}
public string Name
{
set { SetProperty(ref name, value); }
get { return name; }
}
public DateTime BirthDate
{
set { SetProperty(ref birthDate, value); }
get { return birthDate; }
}
public bool CodesInCSharp
{
set { SetProperty(ref codesInCSharp, value); }
get { return codesInCSharp; }
}
public double NumberOfCopies
{
set { SetProperty(ref numberOfCopies, value); }
get { return numberOfCopies; }
}
public NamedColor BackgroundNamedColor
{
set
{
if (SetProperty(ref backgroundNamedColor, value))
{
OnPropertyChanged("BackgroundColor");
}
}
get { return backgroundNamedColor; }
}
public Color BackgroundColor
{
get { return BackgroundNamedColor?.Color ?? Color.White; }
}
public void SaveState(IDictionary<string, object> dictionary)
{
dictionary["Name"] = Name;
dictionary["BirthDate"] = BirthDate;
dictionary["CodesInCSharp"] = CodesInCSharp;
dictionary["NumberOfCopies"] = NumberOfCopies;
dictionary["BackgroundNamedColor"] = BackgroundNamedColor.Name;
}
T GetDictionaryEntry<T>(IDictionary<string, object> dictionary, string key, T defaultValue = default(T))
{
return dictionary.ContainsKey(key) ? (T)dictionary[key] : defaultValue;
}
bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Każde ustawienie aplikacji jest właściwością zapisaną w słowniku Xamarin.Forms właściwości w metodzie o nazwie SaveState
i załadowanej z tego słownika w konstruktorze. W dolnej części klasy są dwie metody, które ułatwiają usprawnianie modelu ViewModel i sprawiają, że są one mniej podatne na błędy. Metoda OnPropertyChanged
w dolnej części zawiera opcjonalny parametr, który jest ustawiony na właściwość wywołującą. Pozwala to uniknąć błędów pisowni podczas określania nazwy właściwości jako ciągu.
Metoda SetProperty
w klasie robi jeszcze więcej: porównuje wartość, która jest ustawiana na właściwość z wartością przechowywaną jako pole, i wywołuje OnPropertyChanged
tylko wtedy, gdy dwie wartości nie są równe.
Klasa SampleSettingsViewModel
definiuje dwie właściwości koloru tła: BackgroundNamedColor
właściwość jest typu NamedColor
, która jest również klasą zawartą w rozwiązaniu DataBindingDemos . Właściwość BackgroundColor
jest typu Color
i jest uzyskiwana z Color
właściwości NamedColor
obiektu.
Klasa NamedColor
używa odbicia platformy .NET w celu wyliczenia wszystkich statycznych pól publicznych w Xamarin.FormsColor
strukturze i przechowywania ich nazw w kolekcji dostępnej z właściwości statycznej All
:
public class NamedColor : IEquatable<NamedColor>, IComparable<NamedColor>
{
// Instance members
private NamedColor()
{
}
public string Name { private set; get; }
public string FriendlyName { private set; get; }
public Color Color { private set; get; }
public string RgbDisplay { private set; get; }
public bool Equals(NamedColor other)
{
return Name.Equals(other.Name);
}
public int CompareTo(NamedColor other)
{
return Name.CompareTo(other.Name);
}
// Static members
static NamedColor()
{
List<NamedColor> all = new List<NamedColor>();
StringBuilder stringBuilder = new StringBuilder();
// Loop through the public static fields of the Color structure.
foreach (FieldInfo fieldInfo in typeof(Color).GetRuntimeFields())
{
if (fieldInfo.IsPublic &&
fieldInfo.IsStatic &&
fieldInfo.FieldType == typeof(Color))
{
// Convert the name to a friendly name.
string name = fieldInfo.Name;
stringBuilder.Clear();
int index = 0;
foreach (char ch in name)
{
if (index != 0 && Char.IsUpper(ch))
{
stringBuilder.Append(' ');
}
stringBuilder.Append(ch);
index++;
}
// Instantiate a NamedColor object.
Color color = (Color)fieldInfo.GetValue(null);
NamedColor namedColor = new NamedColor
{
Name = name,
FriendlyName = stringBuilder.ToString(),
Color = color,
RgbDisplay = String.Format("{0:X2}-{1:X2}-{2:X2}",
(int)(255 * color.R),
(int)(255 * color.G),
(int)(255 * color.B))
};
// Add it to the collection.
all.Add(namedColor);
}
}
all.TrimExcess();
all.Sort();
All = all;
}
public static IList<NamedColor> All { private set; get; }
public static NamedColor Find(string name)
{
return ((List<NamedColor>)All).Find(nc => nc.Name == name);
}
public static string GetNearestColorName(Color color)
{
double shortestDistance = 1000;
NamedColor closestColor = null;
foreach (NamedColor namedColor in NamedColor.All)
{
double distance = Math.Sqrt(Math.Pow(color.R - namedColor.Color.R, 2) +
Math.Pow(color.G - namedColor.Color.G, 2) +
Math.Pow(color.B - namedColor.Color.B, 2));
if (distance < shortestDistance)
{
shortestDistance = distance;
closestColor = namedColor;
}
}
return closestColor.Name;
}
}
Klasa App
w projekcie DataBindingDemos definiuje właściwość o nazwie Settings
typu SampleSettingsViewModel
. Ta właściwość jest inicjowana po utworzeniu App
wystąpienia klasy, a SaveState
metoda jest wywoływana, gdy metoda jest wywoływana OnSleep
:
public partial class App : Application
{
public App()
{
InitializeComponent();
Settings = new SampleSettingsViewModel(Current.Properties);
MainPage = new NavigationPage(new MainPage());
}
public SampleSettingsViewModel Settings { private set; get; }
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
Settings.SaveState(Current.Properties);
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
Aby uzyskać więcej informacji na temat metod cyklu życia aplikacji, zobacz artykuł Cykl życia aplikacji.
Prawie wszystkie inne elementy są obsługiwane w pliku SampleSettingsPage.xaml . Strona BindingContext
jest ustawiana przy użyciu Binding
rozszerzenia znaczników: źródło powiązania jest właściwością statyczną Application.Current
, która jest wystąpieniem App
klasy w projekcie, a Path
właściwość jest ustawiona na Settings
właściwość , która jest obiektem SampleSettingsViewModel
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SampleSettingsPage"
Title="Sample Settings"
BindingContext="{Binding Source={x:Static Application.Current},
Path=Settings}">
<StackLayout BackgroundColor="{Binding BackgroundColor}"
Padding="10"
Spacing="10">
<StackLayout Orientation="Horizontal">
<Label Text="Name: "
VerticalOptions="Center" />
<Entry Text="{Binding Name}"
Placeholder="your name"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Birth Date: "
VerticalOptions="Center" />
<DatePicker Date="{Binding BirthDate}"
HorizontalOptions="FillAndExpand"
VerticalOptions="Center" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Do you code in C#? "
VerticalOptions="Center" />
<Switch IsToggled="{Binding CodesInCSharp}"
VerticalOptions="Center" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Number of Copies: "
VerticalOptions="Center" />
<Stepper Value="{Binding NumberOfCopies}"
VerticalOptions="Center" />
<Label Text="{Binding NumberOfCopies}"
VerticalOptions="Center" />
</StackLayout>
<Label Text="Background Color:" />
<ListView x:Name="colorListView"
ItemsSource="{x:Static local:NamedColor.All}"
SelectedItem="{Binding BackgroundNamedColor, Mode=TwoWay}"
VerticalOptions="FillAndExpand"
RowHeight="40">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<BoxView Color="{Binding Color}"
HeightRequest="32"
WidthRequest="32"
VerticalOptions="Center" />
<Label Text="{Binding FriendlyName}"
FontSize="24"
VerticalOptions="Center" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Wszystkie elementy podrzędne strony dziedziczą kontekst powiązania. Większość innych powiązań na tej stronie to właściwości w pliku SampleSettingsViewModel
. Właściwość BackgroundColor
służy do ustawiania BackgroundColor
właściwości StackLayout
, a Entry
właściwości , DatePicker
Switch
, i Stepper
są powiązane z innymi właściwościami w modelu ViewModel.
Właściwość ItemsSource
właściwości ListView
jest ustawiona na właściwość statyczną NamedColor.All
. Spowoduje to wypełnienie ListView
wszystkich NamedColor
wystąpień. Dla każdego elementu w elemencie ListView
kontekst powiązania dla elementu jest ustawiony na NamedColor
obiekt. Wartości BoxView
i Label
w obiekcie ViewCell
są powiązane z właściwościami w pliku NamedColor
.
Właściwość SelectedItem
typu , i jest powiązana z właściwością BackgroundNamedColor
SampleSettingsViewModel
:NamedColor
ListView
SelectedItem="{Binding BackgroundNamedColor, Mode=TwoWay}"
Domyślnym trybem powiązania dla SelectedItem
elementu jest OneWayToSource
, który ustawia właściwość ViewModel z wybranego elementu. Tryb TwoWay
umożliwia SelectedItem
zainicjowanie elementu z modelu ViewModel.
Jednak po ustawieniu elementu SelectedItem
w ten sposób element nie jest automatycznie przewijany w ListView
celu wyświetlenia wybranego elementu. Potrzebny jest mały kod w pliku za pomocą kodu:
public partial class SampleSettingsPage : ContentPage
{
public SampleSettingsPage()
{
InitializeComponent();
if (colorListView.SelectedItem != null)
{
colorListView.ScrollTo(colorListView.SelectedItem,
ScrollToPosition.MakeVisible,
false);
}
}
}
Zrzut ekranu systemu iOS po lewej stronie przedstawia program po pierwszym uruchomieniu. Konstruktor inicjuje SampleSettingsViewModel
kolor tła na biały, a to, co jest zaznaczone w elemecie ListView
:
Drugi zrzut ekranu przedstawia zmienione ustawienia. Podczas eksperymentowania z tą stroną pamiętaj, aby umieścić program w stanie uśpienia lub przerwać go na urządzeniu lub emulatorze, na którym jest uruchomiony. Zakończenie programu z debugera programu Visual Studio nie spowoduje OnSleep
wywołania przesłonięcia w App
klasie.
W następnym artykule zobaczysz, jak określić formatowanie ciągu powiązań danych ustawionych we Text
właściwości Label
.