Základy datových vazeb
Datové vazby .NET Multi-Platform App UI (.NET MAUI) umožňují propojení vlastností dvou objektů tak, aby změna v jedné z nich způsobuje změnu v druhé. Jedná se o velmi cenný nástroj a zatímco datové vazby je možné definovat zcela v kódu, XAML poskytuje klávesové zkratky a pohodlí.
Datové vazby
Datové vazby spojují vlastnosti dvou objektů, označovaných jako zdroj a cíl. V kódu jsou vyžadovány dva kroky:
- Vlastnost
BindingContext
cílového objektu musí být nastavena na zdrojový objekt. - Metoda
SetBinding
(často použitá ve spojení sBinding
třídou) musí být volána v cílovém objektu, aby bylo možné svázat vlastnost tohoto objektu s vlastností zdrojového objektu.
Cílová vlastnost musí být vlastnost svázatelná, což znamená, že cílový objekt musí být odvozen od BindableObject. Vlastnost Label, například Text
, je přidružena k vázání vlastnost TextProperty
.
V JAZYCE XAML musíte také provést stejné dva kroky, které jsou požadovány v kódu, s tím rozdílem, že Binding
rozšíření značek přebírá místo SetBinding
volání a Binding
třídy. Když však definujete datové vazby v XAML, existuje několik způsobů, jak nastavit BindingContext
cílový objekt. Někdy se nastavuje ze souboru kódu, někdy používá příponu StaticResource
nebo x:Static
značku a někdy jako obsah BindingContext
značek vlastností.
Vazby zobrazení na zobrazení
Datové vazby můžete definovat pro propojení vlastností dvou zobrazení na stejné stránce. V tomto případě nastavíte BindingContext
cílový objekt pomocí x:Reference
rozšíření značek.
Následující příklad obsahuje Slider dvě Label zobrazení, z nichž jedna je otočena Slider hodnotou a druhou, která zobrazuje Slider hodnotu:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SliderBindingsPage"
Title="Slider Bindings Page">
<StackLayout>
<Label Text="ROTATION"
BindingContext="{x:Reference slider}"
Rotation="{Binding Path=Value}"
FontAttributes="Bold"
FontSize="18"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="Center" />
<Label BindingContext="{x:Reference slider}"
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
FontAttributes="Bold"
FontSize="18"
HorizontalOptions="Center"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
Obsahuje Slider x:Name
atribut odkazovaný dvěma Label zobrazeními pomocí x:Reference
rozšíření značek. Rozšíření x:Reference
vazby definuje vlastnost pojmenovanou Name
pro nastavení na název odkazovaného prvku, v tomto případě slider
. Nicméně třída ReferenceExtension
, která definuje x:Reference
rozšíření značek také definuje ContentProperty
atribut pro Name
, což znamená, že není explicitně požadován.
Samotné Binding
rozšíření značek může mít několik vlastností, stejně jako u BindingBase
třídy a Binding
třídy. Hodnota ContentProperty
for Binding
je Path
, ale část "Path=" rozšíření značek může být vynechána, pokud je cesta první položkou Binding
v rozšíření značek.
Binding
Druhé rozšíření značek nastaví StringFormat
vlastnost. V rozhraní .NET MAUI vazby neprovádějí žádné implicitní převody typů, a pokud potřebujete zobrazit objekt bez řetězce jako řetězec, musíte zadat převaděč typů nebo použít StringFormat
.
Důležité
Formátovací řetězce musí být umístěny v jednoduchých uvozovkách.
Režim vazby
Jedno zobrazení může mít datové vazby na několik jeho vlastností. Každé zobrazení však může mít pouze jedno BindingContext
, takže více datových vazeb v daném zobrazení musí všechny odkazovat vlastnosti stejného objektu.
Řešení tohoto a dalších problémů zahrnuje Mode
vlastnost, která je nastavena na člen výčtu BindingMode
:
Default
OneWay
— hodnoty se přenesou ze zdroje do cíle.OneWayToSource
— hodnoty se přenesou z cíle do zdroje.TwoWay
— hodnoty jsou přeneseny oběma způsoby mezi zdrojem a cílem.OneTime
— data pocházejí ze zdroje do cíle, ale pouze v případě, že seBindingContext
změny změní
Následující příklad ukazuje jedno běžné použití OneWayToSource
režimů vazby TwoWay
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SliderTransformsPage"
Padding="5"
Title="Slider Transforms Page">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Scaled and rotated Label -->
<Label x:Name="label"
Text="TEXT"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<!-- Slider and identifying Label for Scale -->
<Slider x:Name="scaleSlider"
BindingContext="{x:Reference label}"
Grid.Row="1" Grid.Column="0"
Maximum="10"
Value="{Binding Scale, Mode=TwoWay}" />
<Label BindingContext="{x:Reference scaleSlider}"
Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
Grid.Row="1" Grid.Column="1"
VerticalTextAlignment="Center" />
<!-- Slider and identifying Label for Rotation -->
<Slider x:Name="rotationSlider"
BindingContext="{x:Reference label}"
Grid.Row="2" Grid.Column="0"
Maximum="360"
Value="{Binding Rotation, Mode=OneWayToSource}" />
<Label BindingContext="{x:Reference rotationSlider}"
Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
Grid.Row="2" Grid.Column="1"
VerticalTextAlignment="Center" />
<!-- Slider and identifying Label for RotationX -->
<Slider x:Name="rotationXSlider"
BindingContext="{x:Reference label}"
Grid.Row="3" Grid.Column="0"
Maximum="360"
Value="{Binding RotationX, Mode=OneWayToSource}" />
<Label BindingContext="{x:Reference rotationXSlider}"
Text="{Binding Value, StringFormat='RotationX = {0:F0}'}"
Grid.Row="3" Grid.Column="1"
VerticalTextAlignment="Center" />
<!-- Slider and identifying Label for RotationY -->
<Slider x:Name="rotationYSlider"
BindingContext="{x:Reference label}"
Grid.Row="4" Grid.Column="0"
Maximum="360"
Value="{Binding RotationY, Mode=OneWayToSource}" />
<Label BindingContext="{x:Reference rotationYSlider}"
Text="{Binding Value, StringFormat='RotationY = {0:F0}'}"
Grid.Row="4" Grid.Column="1"
VerticalTextAlignment="Center" />
</Grid>
</ContentPage>
V tomto příkladu Slider jsou čtyři zobrazení určena k řízení Scale
, Rotate
, RotateX
a RotateY
vlastnosti Label. Zpočátku se zdá, že tyto čtyři vlastnosti Label by měly být cíle datové vazby, protože každá z nich je nastavena pomocí Slider. Může BindingContext
Label však být pouze jeden objekt a existují čtyři různé posuvníky. Z tohoto důvodu je BindingContext
každý ze čtyř posuvníků nastaven na Labela vazby jsou nastaveny na Value
vlastnosti posuvníků. Pomocí a OneWayToSource
režimů mohou tyto Value
vlastnosti nastavit zdrojové vlastnosti, které jsou Scale
, RotateX
Rotate
, a RotateY
vlastnosti Label.TwoWay
Vazby na třech zobrazeních jsou OneWayToSource
, což znamená, že Slider hodnota způsobí změnu vlastnosti jeho BindingContext
, což je pojmenovaný Label label
.Slider Tato tři Slider zobrazení způsobují změny v objektu Rotate
, RotateX
a RotateY
vlastnosti Label:
Vazba pro Scale
vlastnost je TwoWay
však . Důvodem je to, že Scale
vlastnost má výchozí hodnotu 1 a použití vazby TwoWay
způsobí Slider , že počáteční hodnota bude nastavena na hodnotu 1 místo 0. Pokud by tato vazba byla OneWayToSource
, Scale
vlastnost by byla zpočátku nastavena na hodnotu 0 z Slider výchozí hodnoty. Tato Label možnost by nebyla viditelná.
Poznámka:
Třída VisualElement má také vlastnostiScaleY
, které škáluje VisualElement na ose ScaleX
x a y.
Vazby a kolekce
ListViewItemsSource
definuje vlastnost typu IEnumerable
a zobrazí položky v této kolekci. Tyto položky mohou být objekty libovolného typu. Ve výchozím nastavení ListView používá metodu ToString
každé položky k zobrazení této položky. Někdy je to jen to, ToString
co chcete, ale v mnoha případech vrátí pouze plně kvalifikovaný název třídy objektu.
Položky v ListView kolekci lze však zobrazit libovolným způsobem prostřednictvím šablony, která zahrnuje třídu odvozenou z Cell. Šablona se naklonuje pro každou položku v objektu ListViewa datové vazby nastavené v šabloně se přenesou do jednotlivých klonů. Vlastní buňky lze vytvořit pro položky pomocí ViewCell třídy.
ListView může zobrazit seznam všech pojmenovaných barev, které jsou k dispozici v rozhraní .NET MAUI, s pomocí NamedColor
třídy:
using System.Reflection;
using System.Text;
namespace XamlSamples
{
public class NamedColor
{
public string Name { get; private set; }
public string FriendlyName { get; private set; }
public Color Color { get; private set; }
// Expose the Color fields as properties
public float Red => Color.Red;
public float Green => Color.Green;
public float Blue => Color.Blue;
public static IEnumerable<NamedColor> All { get; private set; }
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(Colors).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.
NamedColor namedColor = new NamedColor
{
Name = name,
FriendlyName = stringBuilder.ToString(),
Color = (Color)fieldInfo.GetValue(null)
};
// Add it to the collection.
all.Add(namedColor);
}
}
all.TrimExcess();
All = all;
}
}
}
Každý NamedColor
objekt má Name
a FriendlyName
vlastnosti typu string
, Color
vlastnost typu Color, a Red
, Green
, a Blue
vlastnosti. Kromě toho NamedColor
statický konstruktor vytvoří IEnumerable<NamedColor>
kolekci, která obsahuje NamedColor
objekty odpovídající polím typu Color ve Colors třídě a přiřadí ji ke své veřejné statické All
vlastnosti.
Nastavení statické NamedColor.All
vlastnosti na ItemsSource
hodnotu objektu ListView lze dosáhnout pomocí x:Static
rozšíření značek:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
x:Class="XamlSamples.ListViewDemoPage"
Title="ListView Demo Page">
<ListView ItemsSource="{x:Static local:NamedColor.All}" />
</ContentPage>
Výsledek určí, že položky jsou typu XamlSamples.NamedColor
:
Chcete-li definovat šablonu pro položky, ItemTemplate
měla by být nastavena na odkaz DataTemplate na položku ViewCell. Mělo ViewCell by definovat rozložení jednoho nebo více zobrazení pro zobrazení jednotlivých položek:
<ListView ItemsSource="{x:Static local:NamedColor.All}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding FriendlyName}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Poznámka:
Zdroj vazby pro buňky a podřízené buňky je ListView.ItemsSource
kolekce.
V tomto příkladu Label je prvek nastaven na View vlastnost ViewCell. Značky ViewCell.View
nejsou potřeba, protože View vlastnost je vlastnost ViewCellobsahu . Tento XAML zobrazí vlastnost každého NamedColor
objektuFriendlyName
:
Šablonu položky lze rozšířit, aby se zobrazily další informace a skutečná barva:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
x:Class="XamlSamples.ListViewDemoPage"
Title="ListView Demo Page">
<ContentPage.Resources>
<x:Double x:Key="boxSize">50</x:Double>
<x:Int32 x:Key="rowHeight">60</x:Int32>
<local:FloatToIntConverter x:Key="intConverter" />
</ContentPage.Resources>
<ListView ItemsSource="{x:Static local:NamedColor.All}"
RowHeight="{StaticResource rowHeight}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="5, 5, 0, 5"
Orientation="Horizontal"
Spacing="15">
<BoxView WidthRequest="{StaticResource boxSize}"
HeightRequest="{StaticResource boxSize}"
Color="{Binding Color}" />
<StackLayout Padding="5, 0, 0, 0"
VerticalOptions="Center">
<Label Text="{Binding FriendlyName}"
FontAttributes="Bold"
FontSize="14" />
<StackLayout Orientation="Horizontal"
Spacing="0">
<Label Text="{Binding Red,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat='R={0:X2}'}" />
<Label Text="{Binding Green,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat=', G={0:X2}'}" />
<Label Text="{Binding Blue,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat=', B={0:X2}'}" />
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Převaděče hodnot vazeb
Předchozí příklad XAML zobrazí jednotlivé Red
, Green
a Blue
vlastnosti každého NamedColor
. Tyto vlastnosti jsou typu a jsou v rozsahu float
od 0 do 1. Pokud chcete zobrazit šestnáctkové hodnoty, nemůžete jednoduše použít StringFormat
se specifikací formátování "X2". To funguje pouze pro celá čísla a kromě toho, float
hodnoty musí být vynásobeny 255.
Tento problém lze vyřešit pomocí převaděče hodnot, který se označuje také jako převaděč vazeb. Toto je třída, která implementuje IValueConverter rozhraní, což znamená, že má dvě metody pojmenované Convert
a ConvertBack
. Metoda Convert
je volána při přenosu hodnoty ze zdroje do cíle. Metoda ConvertBack
se volá pro přenosy z cíle do zdroje nebo OneWayToSource
TwoWay
vazby:
using System.Globalization;
namespace XamlSamples
{
public class FloatToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
float multiplier;
if (!float.TryParse(parameter as string, out multiplier))
multiplier = 1;
return (int)Math.Round(multiplier * (float)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
float divider;
if (!float.TryParse(parameter as string, out divider))
divider = 1;
return ((float)(int)value) / divider;
}
}
}
Poznámka:
Metoda ConvertBack
v tomto příkladu nehraje roli, protože vazby jsou pouze jedním způsobem ze zdroje do cíle.
Vazba odkazuje na převaděč vazby Converter
s vlastností. Převaděč vazeb může také přijmout parametr zadaný s ConverterParameter
vlastností. Pro určitou všestrannost je to způsob určení násobitele. Převaděč vazeb zkontroluje, zda parametr převaděče obsahuje platnou float
hodnotu.
Převaděč se vytvoří instance ve slovníku prostředků stránky, takže ho lze sdílet mezi několika vazbami:
<local:FloatToIntConverter x:Key="intConverter" />
Na tuto jednu instanci odkazují tři datové vazby:
<Label Text="{Binding Red,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat='R={0:X2}'}" />
Šablona položky přehrává barvu, její popisný název a jeho hodnoty RGB:
Může ListView zpracovávat změny, které se dynamicky vyskytují v podkladových datech, ale pouze v případě, že provedete určité kroky. Pokud kolekce položek přiřazených k ItemsSource
vlastnosti ListView změny během modulu runtime, použijte ObservableCollection<T> pro tyto položky třídu. ObservableCollection<T> implementuje INotifyCollectionChanged
rozhraní a ListView nainstaluje obslužnou rutinu CollectionChanged
události.
Pokud se vlastnosti samotných položek mění během běhu, měly by položky v kolekci implementovat rozhraní a signalizovat INotifyPropertyChanged
změny hodnot vlastností pomocí PropertyChanged
události.
Další kroky
Datové vazby poskytují výkonný mechanismus pro propojení vlastností mezi dvěma objekty na stránce nebo mezi vizuálními objekty a podkladovými daty. Když ale aplikace začne pracovat se zdroji dat, začne se jako užitečný paradigma objevit oblíbený model architektury aplikace.