WPF temelli uygulamaların en güçlü olduğu konulardan biri elbette “DataBinding” adı verilen veri bağlama mekanizmasıdır.
Bilindiği üzere MVVM (Model-View-View-Model) tasarım kalıbı üzerine inşa edilmiş windows platformları (WPF, Store App, Windows Phone, SilverLight) sunum katmanınızla, uygulama verileriniz arasında çift yönlü senkron veri taşıyabilen “DataBinding” yapısını kullanırlar. Şimdi bu mekanizmanın nasıl kullanıldığına bir bakalım;
İlk olarak uygulama arayüzünü tasarlayalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<Grid Name="grd1"> <Image HorizontalAlignment="Left" Height="111" Margin="112,47,0,0" VerticalAlignment="Top" Width="120" Source="{Binding Img}"/> <TextBlock HorizontalAlignment="Left" Margin="47,182,0,0" TextWrapping="Wrap" Text="ID" VerticalAlignment="Top"/> <TextBlock HorizontalAlignment="Left" Margin="46,214,0,0" TextWrapping="Wrap" Text="NAME" VerticalAlignment="Top"/> <TextBox HorizontalAlignment="Left" Height="23" Margin="112,177,0,0" TextWrapping="Wrap" Text="{Binding Id}" VerticalAlignment="Top" Width="120"/> <TextBox HorizontalAlignment="Left" Height="23" Margin="112,210,0,0" TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Top" Width="120"/> <Button Content="Add" HorizontalAlignment="Left" Margin="112,255,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/> <Button Content="Save" HorizontalAlignment="Left" Margin="203,255,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/> <Button Content="Browse" HorizontalAlignment="Left" Margin="251,131,0,0" VerticalAlignment="Top" Width="53" Click="Button_Click_2"/> <ListBox Name="lst1" HorizontalAlignment="Left" Height="230" Margin="329,61,0,0" VerticalAlignment="Top" Width="154"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Source="{Binding Img}" Stretch="Fill" Width="50" Height="50"/> <TextBox Text="{Binding Name}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> |
Arayüz tasarımında dikkat edeceğimiz bazı hususlar var;
1- Listeleme yapacak olan “lst1” isimli listbox’ın template edilmiş olması. <ListBox>…</Listbox> etiketleri arasında <Listbox.ItemTemplate> ile listbox’ın her bir satırının <DataTemplate> ile bildirilen satır tasarımına sahip olacağı bildirilmiştir. Bu bildirimin içinde tasarımınıza uygun herhangi bir layout tercihinde bulunabilirsiniz. Örneğimiz için <StackPanel> içinde <Image> ve <TextBox> kullandık.
1 2 3 4 5 6 7 8 9 10 |
<ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image Source="{Binding Img}" Stretch="Fill" Width="50" Height="50"/> <TextBox Text="{Binding Name}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> |
2-<DataTemplate> için kullanılan kontrollerimizde {Binding} bildirimleri ile hedeflenen özelliğe, gösterimi yapılacak olan nesnenin özelliği bağlanmıştır.
Sırada “Person” isimli sınıfımızı “Person.cs” isimli dosyada oluşturalım.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public class Person:INotifyPropertyChanged { int _id; public int Id { get { return _id; } set { _id = value; } } string _name; public string Name { get { return _name; } set { _name = value; } } string _img; public string Img { get { return _img; } set { _img = value; propchanged("Img"); } } public event PropertyChangedEventHandler PropertyChanged; private void propchanged(string prop) { if(PropertyChanged!=null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } } |
Sınıf tasarımı normalden biraz farklı olarak “INotifyPropertyChanged” isimli arayüzden türetilmiş olmalıdır. Bu arayüz (interface) şablonuna uygulanmış sınıfların özelliklerinde bir değişim olduğunda yapısında bulunan “PropertyChanged” olayını (event) tetikler. Tabiki bu tetikleme sınıfın özelliklerindeki “set” bloğunda yapılmalıdır. Yukarıda bulunan sınıf örneğimizde “img” isimli özelliğin “set” bloğunda yani bir değer girişi gerçekleştriğinde “propchanged” isimli metoda parametre olarak özelliğin adını metinsel olarak vermektedir. “propchanged(string prop)” metodu “INotifyPropertyChanged” arayüzü ile sınıfımıza dahil olan “PropertyChangedEventHandler” tipindeki “PropertyChanged” olayını (event) tetikleyerek özellik değişimini bildirmektedir.
Bu sayede uygulama arayüzündeki kontrollerimize {binding} ile bağlanmış olan özelliklerin değişiminide gerçekleştirmektedir.
Uygulamanın MainWindow.cs tarafında ise “lst1” isimli Listbox’a kaynak olacak <Person> nesnelerini içinde barındıracak koleksiyonumuzu “ObservableCollection<Person>” tipinde oluşturuyoruz.
1 2 3 |
ObservableCollection<Person> persons = new ObservableCollection<Person>(); |
ListBox’ın “ItemsSource” özelliğine “persons” koleksiyonumuzu bildirerek veri bağlantısını gerçekleştiriyoruz.
1 2 3 |
lst1.ItemsSource = persons; |
Bu aşamadan sonra koleksiyonda yapılacak değişiklikler (Add, Remove) veya koleksiyon içindeki objelerimizde yapılacak herhangi bir özellik değişikliği sonucu ListBox haberdar edilecek ve görünüm tarafında senkron olarak işlenecektir.
Örneğimizin “MainWindow.cs” kodlarını aşağıda bulabilirsiniz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } ObservableCollection<Person> persons = new ObservableCollection<Person>(); Person prs1; private void Window_Loaded(object sender, RoutedEventArgs e) { } private void Button_Click(object sender, RoutedEventArgs e) { prs1 = new Person(); grd1.DataContext = prs1; } private void Button_Click_1(object sender, RoutedEventArgs e) { // persons koleksiyonuna yeni bir <Person> nesnesi eklenmektedir. persons.Add(prs1); lst1.ItemsSource = persons; } private void Button_Click_2(object sender, RoutedEventArgs e) { //Resim dosyası seçilerek <Person> nesnesinin Img özelliğine set edilmektedir. OpenFileDialog file = new OpenFileDialog(); file.ShowDialog(); if(file.FileName!=null) { prs1.Img = file.FileName; } } } |
Aynı şekilde uygulamanın arayüzünde bulunan ID ve Name değerlerini ekranda gösterecek ve değişiklik yapma imkanı sunacak TextBox, Image kontrollerinin de ilgili özelliklerine {Binding} yapıldığını görebilirsiniz. Koleksiyonların ItemSource özelliği yerine bu türden detay gösterimleri için hedef alınan nesneyi kontrollere sahiplik yapan layout’un (Örneğimizde <Grid> kullanıldı) “DataContext” özelliğine bildirilerek sağlanır.
Uygulamanın yapılış videosu:
Dosya için çok teşekkür ederim. Elinize sağlık.
Uygulamanın kodlarını paylaşabilirmisiniz.
Buradan indirebilirsiniz.