XamarinXamarin.Forms

Xamarin.Forms’da Temel Veri Bağlama Kavramı

İçindekiler

Mobil uygulamalarda bazen görünümlerin bağlantılı bir şekilde hareket ettiğini veya bir UI öğesinin dinamik olarak güncellendiğini görmüşsünüzdür. Bu tür etkileşimler bir uygulamanın kullanıcı deneyimini artıran faktörlerdendir. Buna benzer bağlantıları Xamarin.Forms uygulamalarında Veri Bağlama ile yapabilirsiniz.

Veri bağlamaları Xamarin.Forms’un en temel özelliklerinden biridir. Uygulama ile kullanıcının arasında bir köprü kurarak karşılıklı etkileşim halinde olmasını sağlar.

Veri Bağlama Nedir?

Data Bindings (Veri Bağlamaları), Xamarin.Forms uygulamalarında görünümler ile kaynakları ya da görünümler ile görünümleri birbirine bağlamak için kullanılır. Bağlanma işleminden sonra verilerde değişiklik meydana geldiğinde görünümler değişir. Ya da tam tersi görünüm değiştiğinde veriler de değişir.

Örneğin,

  • ContentPage içerisinde tanımlı bir Slider ve BoxView olduğunu varsayalım. Bu slideri BoxView’a bağlayabilir ve Slider’i kaydırdığınızda BoxView’in opaklığını değiştirebilirsiniz.
  • Ya da, ModelView sınıfındaki varolan bir Listeyi ListView’a bağlayabilir ve verileri bir listede görüntüleyebilirsiniz. Hatta ViewModel sınıfında yazacağınız komutlar ile ListView üzerinden bu verilerde değişiklik yapabilirsiniz.
Veri Bağlama Kavramları
Veri Bağlama Kavramları

Veri Bağlamaları temelde dört ana bileşenden oluşur ve her bir bağ bu bileşenleri içerir:

  1. Hedef nesne (Target object)
  2. Hedef özellik (Target property)
  3. Bağlama kaynağı (Binding source)
  4. Yol (Path)

Örneğin, Students adlı bir sınıfın Students.Name özelliğini bir Label’in Text özelliğine bağladığımızı varsayalım. Bu durumda, hedef nesne Label, hedef özellik Text özelliğidir, kullanılan değer Name ve kaynak Students nesnesidir.

Veri Bağlama Modları

Bağlamanın yalnızca kaynaktan hedefe olması gerekmez. Bağlama, uygulamanın nasıl çalıştığına bağlı olarak hedeften kaynağa veya iki yönlü olabilir. Kullanıcının uygulamadaki verileri değiştirmesini isteyip istemediğine göre Bağlama Modunun yönü değişir.

Geliştirdiğiniz projelerde veri bağlama modlarını doğru bir şekilde kulllanıcı deneyimini artırabilirsiniz. Gerektiğinde bir kullanıcıya hem veri göstermeli hem de kullanıcının yapacağı işlemlere göre bu verileri güncellemelisiniz. Böylece kullanıcıyla veri alışverişi yapan dinamik bir uygulama elde edersiniz.

Veri Bağlamada Veri Akışı
Veri Bağlamada Veri Akışı

1)Tek Yönlü Bağlama (OneWay Binding)

OneWay bağlama, kaynaktaki değişikliklerin hedef özelliğini günceller. Yani kaynakta bir değişiklik meydana geldiğinde hedef özelliği değişir. Ancak hedefte yapılan değişiklikler kaynağı güncellemez. Salt okunur verileri bağlamak için kullanmak daha uygundur. Hedefte değişiklik yapılmayacağı durumlarda TwoWay yerine OneWay’e bağlanmak gerekir. Böylece uygulama daha az yük biner.

2)İki Yönlü Bağlama (TwoWay Binding)

TwoWay bağlama ile, kaynak veya hedefteki bir değişik diğerini günceller. Kullanıcı tarafından düzenlenebilir görünüm kaynağa bağlanacaksa TwoWay bağlama daha uygundur. CheckBox, RadioButton gibi UI bileşenleri bu şekilde bağlanmalıdır.

3)OneWayToSource Bağlama (OneWayToSource Binding)

OneWay, bağlamanın tersidir. Adından da anlaşılacağı gibi, hedefteki değişiklik kaynağı günceller.

4)OneTime Bağlama (OneTime Binding)

Kaynak değerinin değişmediği durumlarda, yani verilerin statik olduğu durumlarda kullanılması uygundur. OneTime bağlama, kaynağın hedefi başlatmasına izin verir. Hedefte daha sonraki değişiklikleri yansıtmaz. Yani bir kereliktir. Bu, basit bir OneWay bağlama türüdür.

View To View Veri Bağlama

Xamarin.Forms uygulamalarında, bir görünüm öğesini başka bir görünüm öğesine bağlayabilirsiniz. Böylece, bir görünümdeki değişiklik diğerini günceller. View-to-view bağlamada MVVM modelindeki Model ve ViewModel sınıflarına sınıflarına gerek yoktur. View bileşenlerini birbirine bağlamanız yeterlidir.

Şimdi göstereceğim örnekte, BoxView ile Slider’i birbirine bağlayıp değişiklikleri gözlemleyeceğiz. Ayrıca, Slider’e bir Label bağlayıp Text özelliğini Slider’in değerine göre değiştireceğiz.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Blog.Views.BasicDataBindingPage">
    <ContentPage.Content>
        <StackLayout>
            <Grid  HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
                <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>

                <BoxView x:Name="boxview"
                         BackgroundColor="Gray"
                         HeightRequest="200"
                         HorizontalOptions="Center"
                         VerticalOptions="CenterAndExpand" />
                <Slider x:Name="opacitySlider"
                        Grid.Row="1" Grid.Column="0"
                        Maximum="1"
                        BindingContext="{x:Reference boxview}"
                        Value="{Binding Opacity, Mode=TwoWay}"
                        MaximumTrackColor="Gray"
                        MinimumTrackColor="Gray"/>
                <Label BindingContext="{x:Reference opacitySlider}"
                       Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
                       Grid.Row="1" Grid.Column="1"
                       VerticalTextAlignment="Center"/>
                <Slider x:Name="rotationSlider"
                        Grid.Row="2" Grid.Column="0"
                        Maximum="360"
                        BindingContext="{x:Reference boxview}"
                        Value="{Binding Rotation, Mode=OneWayToSource}"
                        MaximumTrackColor="Gray"
                        MinimumTrackColor="Gray"/>
                <Label BindingContext="{x:Reference rotationSlider}"
                       Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
                       Grid.Row="2" Grid.Column="1"
                       VerticalTextAlignment="Center"
 />
            </Grid>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Burada BoxView’un x: Name değerini Slider’ın BindingContex değerine x: Reference ile bağladım. Ayrıca Slider’ın Value özelliğini BoxView’ın opaklığına bağladım. Etikette, Slider’ı x: Reference ile bağladım ve Text özelliğinin değerini StringFormat ile yazdırdım.

x:Name değeri opacitySlider olan Slider görünümünün bağlama modu TwoWay’dir. Eğer TwoWay yerine OneWayToSource modunda bağlasaydım BoxView görünmeyecekti. Çünkü BoxView’in Opacity özelliğinin başlangıç değeri OneWayToSource modunda bağlansaydı 0 olacaktı. Opacity özelliğinin değerinin 0 yerine 1 olarak ayarlanmasını istediğim için, mod TwoWay yerine OneWayToSource olarak bağladım. Bunlara dikkat edin.

Ekran çıktısı aşağıdaki gibi olur:

ViewToView Veri Bağlama
ViewToView Veri Bağlama

ObservableCollection ile ListView’e Veri Bağlama

Önceki örnekte, bir görünümü başka bir görünüme bağladım. Şimdi ViewModel sınıfında tanımlanan bir ObservableCollection’ı ListView’a nasıl bağlayacağımı göstereceğim. Verileri ListView’a bağlamak, Veri Bağlamaları konusunu daha iyi anlamanıza yardımcı olacaktır. Zaten çoğu uygulamada ListView yapısını sıklıkla kullanacaksınız.

Bu örnekte, öğrenci bilgilerini tutan bir ObservableCollection’u ListView görünümüne bağlayacağım. Dolayısıyla öğrencileri modelleyen bir Model sınıfına ve bu modele göre ObservableCollection oluşturacağım bir ViewModel sınıfına ihtiyacım var. Böylece projeye MVVM modelini uygulamış olacağım. MVVM modeli ile geliştirilen projelerin katmanları birbirinden ayrı geliştirildiği için Seperation of Concers prensibini tam olarak uygulamaktadır. Bu nedenle Xamarin.Forms ile geliştireceğiniz uygulamalarda MVVM modelini kullanmanızı tavsiye ederim.

Şimdi aşağıdaki adımları sırayla uygulayın.

1 Önce projeye bir Model klasörü ekleyin. Ardından bu klasörün içinde Students adlı bir sınıf oluşturun. Bu sınıfta basitçe Number, Name, Surname değişkenleri oluşturun.

public class Student
{
    public int Number { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
}

2 Daha sonra projeye ViewModels adlı bir klasör ekleyin ve bu klasörde StudentViewModel adlı bir sınıf oluşturun. MVVM modelinde ViewModel, View ve Model arasında bağlantı sağlar. Yani bu örnekte StudentViewModel, Model sınıfı ile View arasında bir köprü görevi yapacak. Ardından verilerin işlendiği bir ObservableCollection koleksiyonu oluşturun.

    public class StudentViewModel
    {
        private ObservableCollection<Student> studentList;
        public ObservableCollection<Student> StudentList
        {
            get { return studentList; }
            set
            {
                studentList = value;
            }
        }
        public StudentViewModel()
        {
            StudentList=GetStudents();
        }
        private ObservableCollection<Student> GetStudents()
        {
            return new ObservableCollection<Student>
            {
                new Student{Number=1, Name="Alex",Surname="Doe"},
                new Student{Number=2, Name="Susan",Surname="Cox"},
                new Student{Number=3, Name="Natalia",Surname="Weston"},
                new Student{Number=4, Name="David",Surname="Hahn"}
            };
        }
    }

3 Son olarak, projeye Views adlı bir klasör ekleyin ve bu klasör içinde StudentPage adlı bir ContentPage oluşturun. Ardından, ContenPage’in BindingContext’ini aşağıdaki gibi bildirin.

Sonra BindingContex ile View’a ViewModel’i bağlayın. Yani StudentPage görünümüne StudentViewModel sınıfını bağlayın. Tabi ki gerekli namespace’yi ContentPage tanımına eklemeniz gerekiyor. Eklemezseniz zaten uyarı alacaksınız.

Ardından StackLayout içerisine bir ListView ekleyin ve ItemSource özelliğini StudentList’e bağlayın. Böylece, ListView kaynağının ViewModel sınıfının StudentList adlı ObservableCollection koleksiyonu olduğunu beyan edersiniz. Ek olarak, StudentList’in özelliklerini bağlayarak ViewCell’deki Etiketlerin Text özelliklerinin ListView’de görünmesini sağlayın.

</ContentPage> 
   <ContentPage.BindingContext>
        <bc:StudentViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <ListView ItemsSource="{Binding StudentList}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Horizontal">
                                <Label Text="{Binding Number}" FontSize="20" FontAttributes="Bold" TextColor="Gray" />
                                <Label Text="{Binding Name}" FontSize="20" />
                                <Label Text="{Binding Surname}" FontSize="20" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Ekran çıktısı aşağıdaki gibi olur:

ObservableCollection'u ListView'a Bağlama
ObservableCollection’u ListView’a Bağlama

Veri Bağlama’da Komutlar

Xamarin.Forms uygulamalarında Button, ImageView, Label gibi view bileşenleri ile birkaç yoldan etkileşin kurmak mümkün. Örneğin xaml tarafında bir butona Click eventi vermek ve xaml.cs tarafta da bu methodu yazmak. Böylece butona her tıklandığında bu method çalışır.

Ancak, MVVM modelinde Clicked işleyicisi(handler) olmadığından, etkileşimler Command arabirimi ile sağlanır. Yani ViewModel sınıfında komut nesneleri tanımlanır ve bu komutlar View’daki görünümlere bağlanır.

Yukarıdaki StudentList örneğimde Command arayüzü üzerinden etkileşim kurmak ve listedeki son öğeyi silmek istiyorum. Bunun için, StudentViewModel sınıfında biraz değişiklik yapacağım.

Önce ViewModel sınıfını INotifyPropertyChanged arayüzünden devralıyorum. Ardından bu arayüzün methodlarını implement ediyorum. Daha sonra StudentList içerisine OnPropertyChanged ekliyorum. OnPropertyChanged (“Student”) methodu ile StudentList’de değişiklik olduğunda görünüme haber veriyorum. Böylece, bir öğe silindiğinde ListView bileşeni güncellenecek.

Ayrıca Command’ı nasıl kullandığıma dikkat edin. ViewModel’e bir komut eklemek ve komut yöntemini tanımlamak için ICommand arayüzünü kullanıyorum. Şimdi bu komutu View’a nasıl bağladığımı görelim.

   public class StudentViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        private ObservableCollection<Student> studentList;
        public ObservableCollection<Student> StudentList
        {
            get { return studentList; }
            set
            {
                studentList = value;
                OnPropertyChanged("Student");
            }
        }
        public StudentViewModel()
        {
            StudentList = GetStudents();
        }
        private ObservableCollection<Student> GetStudents()
        {
            return new ObservableCollection<Student>
            {
                new Student{Number=1, Name="Alex",Surname="Doe"},
                new Student{Number=2, Name="Susan",Surname="Cox"},
                new Student{Number=3, Name="Natalia",Surname="Weston"},
                new Student{Number=4, Name="David",Surname="Hahn"}
            };
        }
        public ICommand DeleteCommand => new Command(Delete);
        private async void Delete()
        {
            StudentList.RemoveAt(StudentList.Count-1);
        }
    }

Yukarıdaki örnekteki ContentView içerisine bir Buton ekledim ve Command özelliğini ViewModel’de tanımladığım DeleteCommand ile bağladım. Hepsi bu. Şimdi, butona her tıkladığımızda, ÖğrenciListesinin son elemanı silinecek ve ListView güncellenecektir.

    <ContentPage.BindingContext>
        <bc:StudentViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout>
            <ListView ItemsSource="{Binding StudentList}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Horizontal">
                                <Label Text="{Binding Number}" FontSize="20" FontAttributes="Bold" TextColor="Gray" />
                                <Label Text="{Binding Name}" FontSize="20" />
                                <Label Text="{Binding Surname}" FontSize="20" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button Text="DELETE LAST ITEM" Command="{Binding DeleteCommand}"/>
        </StackLayout>
    </ContentPage.Content>
Veri Baglamada Komutlar
Veri Baglamada Komutlar

Özet

Özet olarak, veri bağlamaları Xamarin.Forms’un en temel özelliklerinden biridir. Veri bağlamaları ile kaynaktaki veri ile hedefteki görünüm birbirine bağlanarak kullanıcıyla uygulama arasındaki etkileşim artırılır. Dolayısıyla uygulamanın kullanıcı deneyimi de artar.

Bu makalede veri bağlamanın temellerini ve veri bağlama modlarını anlattım. Ayrıca çeşitli örneklerle konuyu pekiştirmeye çalıştım. Umarım faydalı olmuştur.

İlgili Makaleler

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu