TOC

This article has been localized into Turkish by the community.

Veri bağlama (data binding):

Değişimlere Cevap Vermek

Şimdiye kadar bu öğreticide UI elemanları veya mevcut sınıflar arasında veri bağlama yaptık. Fakat gerçek dünyada uygulamalarınızda kendi veri nesneleriniz arasında veri bağlaması yapmanız gerekecektir. Bunu yapmak kolay ama bir başladınız mı canınız sıkılacak : Değişimler daha önceki örneklerdeki gibi otomatik olarak güncelleme yapmayacaktır. Bu yazıda göreceğiniz gib bunun için extra çalışmanız gerekecek, fakat WPF işinizi oldukça kolaylaştırıyor.

Veri kaynağındaki değişmelere cevap vermek

Veri kaynağındaki değişmelerle uğraşırken işleyip işlemeyeceğinize karar vermek için iki değişik senaryo vardır : Bir elemanlar listesindeki değişim ve veri nesnelerinin bağlı özelliklerinde olan değişim. Bunları nasıl işleyeceğiniz, ne iş yaptığınız ve neyi amaçladığınıza göre değişir, fakat WPF bu amaçla kullanabileceğiniz çözümler sunar : ObservableCollection listesi ve INotifyPropertyChanged Interface.

Aşağıdaki örnek bu iki şeye neden ihtiyacımız olduğunu gösteriyor :

<Window x:Class="WpfTutorialSamples.DataBinding.ChangeNotificationSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ChangeNotificationSample" Height="150" Width="300">
	<DockPanel Margin="10">
		<StackPanel DockPanel.Dock="Right" Margin="10,0,0,0">
			<Button Name="btnAddUser" Click="btnAddUser_Click">Add user</Button>
			<Button Name="btnChangeUser" Click="btnChangeUser_Click" Margin="0,5">Change user</Button>
			<Button Name="btnDeleteUser" Click="btnDeleteUser_Click">Delete user</Button>
		</StackPanel>
		<ListBox Name="lbUsers" DisplayMemberPath="Name"></ListBox>
	</DockPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;

namespace WpfTutorialSamples.DataBinding
{
	public partial class ChangeNotificationSample : Window
	{
		private List<User> users = new List<User>();

		public ChangeNotificationSample()
		{
			InitializeComponent();

			users.Add(new User() { Name = "John Doe" });
			users.Add(new User() { Name = "Jane Doe" });

			lbUsers.ItemsSource = users;
		}

		private void btnAddUser_Click(object sender, RoutedEventArgs e)
		{
			users.Add(new User() { Name = "New user" });
		}

		private void btnChangeUser_Click(object sender, RoutedEventArgs e)
		{
			if(lbUsers.SelectedItem != null)
				(lbUsers.SelectedItem as User).Name = "Random Name";
		}

		private void btnDeleteUser_Click(object sender, RoutedEventArgs e)
		{
			if(lbUsers.SelectedItem != null)
				users.Remove(lbUsers.SelectedItem as User);
		}
	}

	public class User
	{
		public string Name { get; set; }
	}
}

Çalıştırıp kontrol edin, listeye bir şey eklemeye çalışın, birini değiştirmeye çalışın UI'de hiç bir şey güncellenmez. Örnek oldukça basit kullanıcı adını saklayan bir User sınıfı, kullanıcıları gösteren bir ListBox ve veriyi değiştiren birkaç Button. Listenin ItemsSource özelliğine pencere kurulumunda bir iki tane yeni kullanıcı ile oluşturduğumuz listeyi verdik. Problem şu ki hiç bir Button çalışmıyor. Hadi bunu iki kolay adımda düzeltelim.

Değişimleri listenin veri kaynağına yansıtmak

Bir kullanıcı eklemek veya değiştirmek gibi yaptığımız listenin kaynağında (ItemSource) değişikliklere UI'nin cevap vermesi ilk adımdır. İhtiyacımız olan içeriğindeki değişimleri hedeflerine bildiren bir liste, ve ne mutlu ki WPF bize böyle bir liste sunuyor, ObservableCollection. Bir kaç fark dışında standart List<T>, ile aynı.

Aşağıda bulacağınız final örnekte basitçe List<User> tanımlamasını ObservableCollection<User> ile değiştirdik - sadece bunu yaparak Add ve Delete butonlarının çalışmasını sağlarız, ama "Change name" butonunu etkilemez, çünkü değişim değişim bağlı veri nesnesinin kendisinde oluyor ama kaynak listede değil - ikinci adım da bunu düzenleyecek tabi ki.

Veri nesnesi içindeki değişimlerin yansıtılması

İkinci adım bizim kendi tanımladığımız User sınıfına INotifyPropertyChanged arabirimini uygulamak. Bunu yaparak bizim User nesnemiz özellik değişince UI seviyesinde değişimi bildirecektir. Bu sadece liste tipini değiştirmekten biraz daha külfetli bir iş, fakat yine de otomatik güncelleme yapmanın en basit yolu.

Son ve çalışan örnek

Yukarıda bahsedilen iki değişiklikle biz artık gerçekten veri kaynağındaki değişimi yansıtan bir örneğe sahibiz. Şuna benziyor :

<Window x:Class="WpfTutorialSamples.DataBinding.ChangeNotificationSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ChangeNotificationSample" Height="135" Width="300">
	<DockPanel Margin="10">
		<StackPanel DockPanel.Dock="Right" Margin="10,0,0,0">
			<Button Name="btnAddUser" Click="btnAddUser_Click">Add user</Button>
			<Button Name="btnChangeUser" Click="btnChangeUser_Click" Margin="0,5">Change user</Button>
			<Button Name="btnDeleteUser" Click="btnDeleteUser_Click">Delete user</Button>
		</StackPanel>
		<ListBox Name="lbUsers" DisplayMemberPath="Name"></ListBox>
	</DockPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace WpfTutorialSamples.DataBinding
{
	public partial class ChangeNotificationSample : Window
	{
		private ObservableCollection<User> users = new ObservableCollection<User>();

		public ChangeNotificationSample()
		{
			InitializeComponent();

			users.Add(new User() { Name = "John Doe" });
			users.Add(new User() { Name = "Jane Doe" });

			lbUsers.ItemsSource = users;
		}

		private void btnAddUser_Click(object sender, RoutedEventArgs e)
		{
			users.Add(new User() { Name = "New user" });
		}

		private void btnChangeUser_Click(object sender, RoutedEventArgs e)
		{
			if(lbUsers.SelectedItem != null)
				(lbUsers.SelectedItem as User).Name = "Random Name";
		}

		private void btnDeleteUser_Click(object sender, RoutedEventArgs e)
		{
			if(lbUsers.SelectedItem != null)
				users.Remove(lbUsers.SelectedItem as User);
		}
	}

	public class User : INotifyPropertyChanged
	{
		private string name;
		public string Name {
			get { return this.name; }
			set
			{
				if(this.name != value)
				{
					this.name = value;
					this.NotifyPropertyChanged("Name");
				}
			}
		}

		public event PropertyChangedEventHandler PropertyChanged;

		public void NotifyPropertyChanged(string propName)
		{
			if(this.PropertyChanged != null)
				this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
		}
	}
}

Sonuç

Gördüğünüz üzere INotifyPropertyChanged arabirimini uygulamak kolay ama sınıf tanımlarınızda extra kod ve özellik tanımlarınıza extra lojik ilavesi gerektirir. Bu da kendi tanımladığınız sınıflardaki verilerin UI de anında güncellemeler yapmasının bedeli. Açıkçası eğer başka özellik de varsa sadece bağlanmak istediğiniz özelliğin set bloğunda NotifyPropertyChanged çağıracaksınız - Gerisi olduğu gibi kalabilir.

Diğer taraftan ObservableCollection'la başetmek çok daha kolay - bir veri bağlama hedefine listedeki değişimleri yansıtmak istiyorsanız bu özel liste tipinde tanımlama yaparsınız.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!