Bölüm 4. Temel Veri Bağlama Bilgileri
Veri bağlamaları, iki nesnenin özelliklerinin bağlanmasına izin verir, böylece bir nesnedeki bir değişiklik diğerinde değişikliğe neden olur. Bu çok değerli bir araçtır ve veri bağlamaları tamamen kodda tanımlanabilirken, XAML kısayollar ve kolaylık sağlar. Sonuç olarak, içindeki Xamarin.Forms en önemli işaretleme uzantılarından biri Bağlama'dır.
Veri Bağlamaları
Veri bağlamaları, kaynak ve hedef olarak adlandırılan iki nesnenin özelliklerini bağlar. Kodda iki adım gerekir: BindingContext
Hedef nesnenin özelliği kaynak nesneye ayarlanmalıdır ve SetBinding
bu nesnenin bir özelliğini kaynak nesnenin özelliğine bağlamak için hedef nesnede yöntemi (genellikle sınıfla Binding
birlikte kullanılır) çağrılmalıdır.
Hedef özelliği bağlanabilir bir özellik olmalıdır, bu da hedef nesnenin öğesinden BindableObject
türetilmesi gerektiği anlamına gelir. Çevrimiçi Xamarin.Forms belgeler, hangi özelliklerin bağlanabilir özellikler olduğunu gösterir. gibi Text
bir Label
özelliği, bağlanabilir özelliğiyle TextProperty
ilişkilendirilir.
İşaretlemeyi yaparken, işaretleme uzantısının çağrının ve Binding
sınıfın yerini SetBinding
alması dışında Binding
kodda gerekli olan iki adımı da gerçekleştirmeniz gerekir.
Ancak, XAML'de veri bağlamaları tanımladığınızda, hedef nesnenin ayarlanmasının BindingContext
birden çok yolu vardır. Bazen arka planda kod dosyasından, bazen bir StaticResource
veya x:Static
işaretleme uzantısı kullanılarak, bazen de özellik öğesi etiketlerinin BindingContext
içeriği olarak ayarlanır.
Bağlamalar en sık, Bölüm 5'te açıklandığı gibi MVVM (Model-View-ViewModel) uygulama mimarisinin gerçekleştirilmesinde bir programın görsellerini temel alınan veri modeline bağlamak için kullanılır. Veri Bağlamalarından MVVM'ye, ancak diğer senaryolar mümkündür.
Görünümden Görünüme Bağlamalar
Aynı sayfadaki iki görünümün özelliklerini bağlamak için veri bağlamaları tanımlayabilirsiniz. Bu durumda, işaretleme uzantısını kullanarak hedef nesnenin x:Reference
değerini ayarlarsınızBindingContext
.
Aşağıda, biri değer tarafından Slider
döndürülen ve diğeri değeri görüntüleyen bir Slider
ve iki Label
görünüm içeren bir XAML dosyası yer alırSlider
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SliderBindingsPage"
Title="Slider Bindings Page">
<StackLayout>
<Label Text="ROTATION"
BindingContext="{x:Reference Name=slider}"
Rotation="{Binding Path=Value}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="CenterAndExpand" />
<Label BindingContext="{x:Reference slider}"
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
, Slider
işaretleme uzantısı kullanılarak iki Label
görünüm tarafından başvuruda bulunan x:Reference
bir x:Name
öznitelik içerir.
Bağlama x:Reference
uzantısı, bu örnekte slider
başvuruda bulunan öğesinin adına ayarlamak için adlı Name
bir özellik tanımlar. Ancak, ReferenceExtension
işaretleme uzantısını x:Reference
tanımlayan sınıf için Name
bir ContentProperty
özniteliği de tanımlar; bu da açıkça gerekli olmadığı anlamına gelir. Yalnızca çeşitlilik için, ilki x:Reference
"Name=" içerir, ancak ikincisi şunları içermez:
BindingContext="{x:Reference Name=slider}"
…
BindingContext="{x:Reference slider}"
İşaretlemeyi Binding
uzantısının kendisi de ve Binding
sınıfı gibi çeşitli özelliklere BindingBase
sahip olabilir. ContentProperty
için Binding
şeklindedirPath
, ancak yol işaretleme uzantısındaki ilk öğeyseBinding
, işaretleme uzantısının "Path=" bölümü atlanabilir. İlk örnekte "Path=" var, ancak ikinci örnek bunu atlar:
Rotation="{Binding Path=Value}"
…
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
Özelliklerin tümü bir satırda veya birden çok satıra ayrılabilir:
Text="{Binding Value,
StringFormat='The angle is {0:F0} degrees'}"
Uygun olan her şeyi yap.
StringFormat
İkinci Binding
işaretleme uzantısında özelliğine dikkat edin. içinde Xamarin.Formsbağlamalar örtük tür dönüştürmeleri gerçekleştirmez ve dize olmayan bir nesneyi dize olarak görüntülemeniz gerekiyorsa bir tür dönüştürücüsü sağlamanız veya kullanmanız StringFormat
gerekir. Arka planda, statik String.Format
yöntemi uygulamak StringFormat
için kullanılır. .NET biçimlendirme belirtimleri, işaretleme uzantılarını sınırlandırmak için de kullanılan küme ayraçları içerdiğinden, bu büyük olasılıkla bir sorundur. Bu, XAML ayrıştırıcısını karıştırma riski oluşturur. Bunu önlemek için biçimlendirme dizesinin tamamını tek tırnak içine alın:
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
Çalışan program şu şekildedir:
Bağlama Modu
Tek bir görünümde, özelliklerinin birkaçı üzerinde veri bağlamaları olabilir. Ancak, her görünümde yalnızca bir BindingContext
olabilir, bu nedenle bu görünümdeki birden çok veri bağlaması aynı nesnenin tüm başvuru özelliklerine sahip olmalıdır.
Bu ve diğer sorunların çözümü, numaralandırmanın Mode
bir üyesine BindingMode
ayarlanan özelliği içerir:
Default
OneWay
— değerler kaynaktan hedefe aktarılırOneWayToSource
— değerler hedeften kaynağa aktarılırTwoWay
— değerler hem kaynak hem de hedef arasında aktarılırOneTime
— veriler kaynaktan hedefe gider, ancak yalnızcaBindingContext
değişiklikler
Aşağıdaki program, ve TwoWay
bağlama modlarının OneWayToSource
yaygın kullanımlarından birini gösterir. Dört Slider
görünüm, bir Label
öğesinin Scale
, Rotate
, RotateX
ve RotateY
özelliklerini denetlemek için tasarlanmıştır. İlk başta, her biri tarafından Slider
ayarlandığı için bu dört özelliğinin Label
veri bağlama hedefleri olması gerekir gibi görünüyor. Ancak , BindingContext
Label
yalnızca bir nesne olabilir ve dört farklı kaydırıcı vardır.
Bu nedenle, tüm bağlamalar görünüşte geriye dönük olarak ayarlanır: BindingContext
Dört kaydırıcının her biri değerine ayarlanır Label
ve bağlamalar kaydırıcıların özelliklerine Value
göre ayarlanır. ve modlarını OneWayToSource
kullanarak, bu Value
özellikler , , RotateX
ve RotateY
özellikleri olan Scale
Rotate
kaynak özelliklerini Label
ayarlayabilir:TwoWay
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
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>
Görünümlerin üçindeki Slider
bağlamalar şeklindedirOneWayToSource
, yani Slider
değeri adlı label
öğesinin BindingContext
özelliğinde değişikliğe neden olurLabel
. Bu üç Slider
görünüm, içinde , RotateX
ve RotateY
özelliklerinde değişikliklere Rotate
Label
neden olur.
Ancak, özelliğinin bağlaması Scale
olur TwoWay
. Bunun nedeni, özelliğin Scale
varsayılan değeri 1 olması ve bağlama kullanılması TwoWay
ilk değerin Slider
0 yerine 1 olarak ayarlanmasına neden olmasıdır. Bu bağlama olsaydı OneWayToSource
Scale
özelliği başlangıçta varsayılan değerden Slider
0 olarak ayarlanırdı. Label
görünür olmayacaktır ve bu durum kullanıcının kafa karışıklığına neden olabilir.
Not
Sınıfın VisualElement
ayrıca ve özellikleri vardır ScaleX
ve ScaleY
bu özellikler sırasıyla x ekseni ve y ekseni üzerinde ölçeklendirilir VisualElement
.
Bağlamalar ve Koleksiyonlar
Hiçbir şey XAML'nin gücünü ve veri bağlamalarını şablonlu değerinden daha iyi gösterelememektedir ListView
.
ListView
türünde IEnumerable
bir ItemsSource
özellik tanımlar ve bu koleksiyondaki öğeleri görüntüler. Bu öğeler herhangi bir türde nesneler olabilir. Varsayılan olarak, ListView
bu öğeyi ToString
görüntülemek için her öğenin yöntemini kullanır. Bazen istediğiniz şey bu olsa da çoğu durumda ToString
nesnenin yalnızca tam sınıf adını döndürür.
Ancak koleksiyondaki ListView
öğeler, öğesinden Cell
türetilen bir sınıfı içeren bir şablon kullanarak istediğiniz şekilde görüntülenebilir. Şablon içindeki ListView
her öğe için kopyalanır ve şablonda ayarlanan veri bağlamaları tek tek kopyalara aktarılır.
Çoğu zaman sınıfını kullanarak ViewCell
bu öğeler için özel bir hücre oluşturmak istersiniz. Bu işlem kodda biraz karmaşıktır, ancak XAML'de çok basit hale gelir.
XamlSamples projesine dahil edilen adlı bir sınıftır NamedColor
. Her NamedColor
nesnenin türü string
ve FriendlyName
özellikleri ve türünde Color
bir Color
özelliği vardırName
. Ayrıca, NamedColor
sınıfında tanımlanan Xamarin.FormsColor
renklere karşılık gelen türdeki 141 statik salt okunur alanı Color
vardır. Statik oluşturucu, bu statik alanlara karşılık gelen nesneleri içeren NamedColor
bir IEnumerable<NamedColor>
koleksiyon oluşturur ve bunu genel statik All
özelliğine atar.
İşaretlemeyi ItemsSource
kullanarak x:Static
statik NamedColor.All
özelliğin ListView
değerine ayarlanması kolaydır:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
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>
Sonuçta elde edilen görüntü, öğelerin gerçekten türünde XamlSamples.NamedColor
olduğunu belirler:
Bu çok fazla bilgi değildir, ancak ListView
kaydırılabilir ve seçilebilir.
Öğeler için bir şablon tanımlamak için özelliği bir özellik öğesi olarak ayırmak ItemTemplate
ve bunu olarak DataTemplate
ayarlamak ve ardından öğesine ViewCell
başvurmak isteyeceksiniz. View
özelliğinin özelliğineViewCell
, her öğeyi görüntülemek için bir veya daha fazla görünümün düzenini tanımlayabilirsiniz. İşte basit bir örnek:
<ListView ItemsSource="{x:Static local:NamedColor.All}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Label Text="{Binding FriendlyName}" />
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Not
Hücrelerin ve hücrelerin alt öğelerinin bağlama kaynağı koleksiyondur ListView.ItemsSource
.
Label
öğesi öğesinin View
özelliğine ViewCell
ayarlanır. (özelliği öğesinin ViewCell.View
View
içerik özelliği ViewCell
olduğundan etiketler gerekli değildir.) Bu işaretleme her NamedColor
nesnenin FriendlyName
özelliğini görüntüler:
Çok daha iyi. Artık tek gereken, öğe şablonunu daha fazla bilgi ve gerçek renkle ladinlendirmektir. Bu şablonu desteklemek için sayfanın kaynak sözlüğünde bazı değerler ve nesneler tanımlanmıştır:
<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.ListViewDemoPage"
Title="ListView Demo Page">
<ContentPage.Resources>
<ResourceDictionary>
<OnPlatform x:Key="boxSize"
x:TypeArguments="x:Double">
<On Platform="iOS, Android, UWP" Value="50" />
</OnPlatform>
<OnPlatform x:Key="rowHeight"
x:TypeArguments="x:Int32">
<On Platform="iOS, Android, UWP" Value="60" />
</OnPlatform>
<local:DoubleToIntConverter x:Key="intConverter" />
</ResourceDictionary>
</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="Medium" />
<StackLayout Orientation="Horizontal"
Spacing="0">
<Label Text="{Binding Color.R,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat='R={0:X2}'}" />
<Label Text="{Binding Color.G,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat=', G={0:X2}'}" />
<Label Text="{Binding Color.B,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat=', B={0:X2}'}" />
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
bir boyutunu ve satırların BoxView
yüksekliğini tanımlamak için kullanımına OnPlatform
ListView
dikkat edin. Tüm platformların değerleri aynı olsa da, işaretleme diğer değerlere göre kolayca uyarlanabilir ve ekranda ince ayar yapılabilir.
Bağlama Değeri Dönüştürücüleri
Önceki ListView Demo XAML dosyası, yapının tek tek R
, G
ve B
özelliklerini Xamarin.FormsColor
görüntüler. Bu özellikler türündedir double
ve 0 ile 1 arasındadır. Onaltılık değerleri görüntülemek istiyorsanız, yalnızca "X2" biçimlendirme belirtimi ile kullanamazsınız StringFormat
. Bu yalnızca tamsayılar için geçerlidir ve bunun yanı sıra, değerlerin double
255 ile çarpılması gerekir.
Bu küçük sorun, bağlama dönüştürücüsü olarak da adlandırılan bir değer dönüştürücüsü ile çözüldü. Bu, ve adlı Convert
ConvertBack
iki yöntemi olduğu anlamına gelen arabirimini uygulayan IValueConverter
bir sınıftır. Bir Convert
değer kaynaktan hedefe aktarıldığında yöntemi çağrılır; ConvertBack
veya bağlamalarında OneWayToSource
TwoWay
hedeften kaynağa aktarımlar için yöntemi çağrılır:
using System;
using System.Globalization;
using Xamarin.Forms;
namespace XamlSamples
{
class DoubleToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
double multiplier;
if (!Double.TryParse(parameter as string, out multiplier))
multiplier = 1;
return (int)Math.Round(multiplier * (double)value);
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
double divider;
if (!Double.TryParse(parameter as string, out divider))
divider = 1;
return ((double)(int)value) / divider;
}
}
}
ConvertBack
Bağlamalar kaynaktan hedefe yalnızca bir yol olduğundan yöntemi bu programda rol oynamaz.
Bağlama, özelliğiyle bir bağlama dönüştürücüsünü başvurur Converter
. Bağlama dönüştürücüsü özelliğiyle belirtilen bir parametreyi ConverterParameter
de kabul edebilir. Çok yönlülük için çarpan bu şekilde belirtilir. Bağlama dönüştürücüsü, dönüştürücü parametresini geçerli double
bir değer için denetler.
Dönüştürücü, birden çok bağlama arasında paylaşılabilmesi için kaynak sözlüğünde örneği oluşturulur:
<local:DoubleToIntConverter x:Key="intConverter" />
Üç veri bağlaması bu tek örneğe başvurur. İşaretlemeyi uzantısının Binding
eklenmiş StaticResource
bir işaretleme uzantısı içerdiğine dikkat edin:
<Label Text="{Binding Color.R,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat='R={0:X2}'}" />
Sonuç şu şekildedir:
ListView
, yalnızca belirli adımları uygulamanız durumunda temel alınan verilerde dinamik olarak gerçekleşebilecek değişiklikleri işleme konusunda oldukça karmaşıktır. Çalışma zamanı sırasında değişikliklerin özelliğine ListView
atanan öğe koleksiyonu (yani koleksiyona ItemsSource
öğe eklenebiliyorsa veya koleksiyondan kaldırılabiliyorsa), bu öğeler için bir ObservableCollection
sınıf kullanın. ObservableCollection
arabirimini INotifyCollectionChanged
uygular ve ListView
olay için CollectionChanged
bir işleyici yükler.
Çalışma zamanı sırasında öğelerin özellikleri değişirse, koleksiyondaki öğeler arabirimini uygulamalı INotifyPropertyChanged
ve olayı kullanarak özellik değerlerine değişiklik sinyali vermelidir PropertyChanged
. Bu, bu serinin sonraki bölümü olan Bölüm 5'te gösterilmiştir. Veri Bağlama'dan MVVM'ye.
Özet
Veri bağlamaları, bir sayfadaki iki nesne arasında veya görsel nesnelerle temel alınan veriler arasında özellikleri bağlamak için güçlü bir mekanizma sağlar. Ancak uygulama veri kaynaklarıyla çalışmaya başladığında, popüler bir uygulama mimari düzeni yararlı bir paradigma olarak ortaya çıkmaya başlar. Bu, Bölüm 5'te ele alınmıştır. Veri Bağlamalarından MVVM'ye.