Makale Özeti

Bu makalemde sizlerle INotifyPropertyChanged interface'ini temel olarak, nerelerde kullanılabileceğini inceleyeceğiz ve küçük bir örnek yapacağız. Adından da anlaşılabileceği gibi INotifyPropertyChanged değişen property'lere ait değerleri yakalamak için kullanılır. Bu interface'e baktığımızda içerisinde PropertyChanged isminde bir event olduğunu görüyoruz. Bu event herhangi bir property'nin değeri değiştiğinde fırlayacak olan event'tir.

Makale

Merhabalar,

Bu makalemde sizlerle INotifyPropertyChanged interface'ini temel olarak, nerelerde kullanılabileceğini inceleyeceğiz ve küçük bir  örnek yapacağız.

Adından da anlaşılabileceği gibi INotifyPropertyChanged değişen property'lere ait değerleri yakalamak için kullanılır. Bu interface'e baktığımızda içerisinde PropertyChanged isminde bir event olduğunu görüyoruz. Bu event herhangi bir property'nin değeri değiştiğinde fırlayacak olan event'tir.

Ek bir bilgi olarak vermek gerekirse INotifyCollectionChanged ise Collection'a ait herhangi bir üye değiştiğinde kullanılır. Bu interface'in içeriğine baktığımızda CollectionChanged isminde bir evenet olduğunu göryoruz. Bu evet collection üzerinde herhangi bir değişiklik olduğunda fırlayacak event'tir.

Özellikle MVVM pattern'i kullandığınız uygulamaların temeli DataBinging olduğundan bu interface'i kullanmanız kaçılmazdır. Collection kullanmak gereken durumlarda ise ObservableCollecion generic tipini kullanmak bu tip INotifyCollectionChanged ve INotifyPropertyChanged interfacelerini barındırdığından çok daha uygun olacaktır ve implemantasyonu çok daha kolaydır.

İsterseniz bu özelliklerin nasıl kullanıldığını örnek uygulamamız üzerinde inceleyelim.

Yapacağımız örneği arabalarının anlık hızlarını takip etmek için kullanan bir şirket senaryosunu canlandıralım. Örneğimizde herhangi bir dış kaynaktan veri okumadığımız için araçların hızlarını güncellemeyi bir timer nesnesi üzerinden yapacağız. Tüm örneklerimizde aynı ekranı kullanacağız bu sayede metodlar arasındaki avantaj ve dezavantajları karşılaştırabileceğiz.

İlk örneğimizde bir çoğumuzun uygulamalarda kullandığı basit bir araba nesnesi üzerinden çalışalım ve şirketimize ait arabaları ve hızlarını gridimizde gösterelim. Formumuzu aşağıdaki gibi tasarlıyoruz. Tasarımda gözükmeyen bir de timer kontrolümüz var unutmamamız gerek. Yaptığımız 2 örnekte de aynı formu kullanacağız.

Ekran görüntüsünde gördüğünüz gibi 1 button ve 1 gridden oluan bir form. Initiate Cars ile sahadaki arabalarımızın listesini gride yükleyeceğiz. Saniyede bir çalışması için kurduğumuz timer ise arabalarımızın hızını güncellemeyi simule edecek.

Öncelikle araba class'ımızı oluşturalım.

    public class SimpleCar
    {
        public string Plate { get; set; }
        public string Driver { get; set; }
        public int CurrentSpeed { get; set; }
    }

Şimdi ise formumuzun kodunu yazalım.

    public partial class SimpleCarForm : Form
    {
        public SimpleCarForm()
        {
            InitializeComponent();
        }
        BindingList<SimpleCar> cars = new BindingList<SimpleCar>();
        BindingSource bs = new BindingSource();
        private void Form1_Load(object sender, EventArgs e)
        {
 
        }
        private void timerUpdateCurrentSpeeds_Tick(object sender, EventArgs e)
        {
            Random r = new Random();
            foreach (SimpleCar sc in cars)
            {
                sc.CurrentSpeed = r.Next(30, 120);
            }
        }
      
        private void btnInitiateCars_Click(object sender, EventArgs e)
        {
            SimpleCar sc1 = new SimpleCar { Plate = "34 AAA 34", Driver = "Mustafa", CurrentSpeed = 0 };
            SimpleCar sc2 = new SimpleCar { Plate = "34 BBB 34", Driver = "Ahmet", CurrentSpeed = 0 };
            SimpleCar sc3 = new SimpleCar { Plate = "34 CCC 34", Driver = "Mehmet", CurrentSpeed = 0 };
            cars.Add(sc1);
            cars.Add(sc2);
            cars.Add(sc3);
 
            bs.DataSource = cars;
            grvCars.DataSource = bs;
        }
    }

Gördüğünüz gibi Initiate Cars metodunda araba listesini yüklüyoruz. Burdaki yükleme işlemlerini direkt olarak datasource'a list vererek değilde bu şekilde yaptım ki her iki örneğimizde de aynı kodu kullanalım. Formu çalıştırıp InitiateCars buton'una tıkladığımızda timer çalışmasına rağmen griddeki hiçbir hız bilgisinin güncellenmediğini görüyoruz. Gridi güncellemek için gride veriyi tekrar bind etmemiz gerekiyor.

Şimdi ise Car INotifyPropertyChanged'ın kullanım alanını inceleyelim. İkinci örneğimizde yine bir araba nesnesi oluşturalım. Ancak bu sefer INotifyPropertyChanged İnterface'inin implement edelim.

    public class Car : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        private void NotifyPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
 
        public Car(string plate, string driver)
        {
            _Plate = plate;
            _Driver = driver;
        }
        private string _Plate = string.Empty;
        public string Plate
        {
            get
            {
                return _Plate;
            }
            set
            {
                if (_Plate != value)
                {
                    _Plate = value;
                    NotifyPropertyChanged("Plate");
                }
            }
        }
        private string _Driver = string.Empty;
        public string Driver
        {
            get
            {
                return _Driver;
            }
            set
            {
                if (_Driver != value)
                {
                    _Driver = value;
                    NotifyPropertyChanged("Driver");
                }
            }
        }
        private int _CurrentSpeed = 0;
        public int CurrentSpeed
        {
            get
            {
                return _CurrentSpeed;
            }
            set
            {
                if (_CurrentSpeed != value)
                {
                    _CurrentSpeed = value;
                    NotifyPropertyChanged("CurrentSpeed");
                }
            }
        }

 Gördüğünüz gibi interface'i implement ettiğimizde bir event geliyor ve biz property'lerin değeri değiştiğinde bu event'ı fırlatıyoruz. Formumuzun koduna tekrar göz atalım.

public partial class CarForm : Form
    {
        public CarForm()
        {
            InitializeComponent();
        }
        BindingList<Car> cars = new BindingList<Car>();
        BindingSource bs = new BindingSource();
        private void Form1_Load(object sender, EventArgs e)
        {
 
        }
 
        private void timerUpdateCurrentSpeeds_Tick(object sender, EventArgs e)
        {
            Random r = new Random();
            foreach (Car sc in cars)
            {
                sc.CurrentSpeed = r.Next(30, 120);
            }
        }
 
        private void btnInitiateCars_Click(object sender, EventArgs e)
        {
            Car sc1 = new Car("34 AAA 34", "Mustafa");
            Car sc2 = new Car("34 BBB 34", "Ahmet");
            Car sc3 = new Car("34 CCC 34", "Mehmet");
            cars.Add(sc1);
            cars.Add(sc2);
            cars.Add(sc3);
 
            bs.DataSource = cars;
            grvCars.DataSource = bs;
        }
    }

Şimdi isterseniz Program.cs'den başlangıç formumuzu değiştirerek yeni formumuzu çalıştıralım. Gördüğünüz gibi hız değerleri kendi kendine değişiyor.  Bizim UI tarafında herhangi bir kod değişikliği yapmamıza gerek kalmadı.

Ayrıca bu interfce'i implement eden class'lar üzerinden PropertyChanged event'ine subscribe olarak bir değer değiştiği gibi kendi işlerimizin yapılmasını da sağlamamız mümkün. Her ne kadar Domain prensiplerine uymasa da değişen nesnenin mail atılması, nesnelerin statelerinin tutulması gibi işlemler buna örnek olarak gösterilebilir. Umarım faydalı bir makale olmuştur.

 

 

Ornek Kodlar