INotifyPropertyChanged Nedir Nasıl Kullanılır

WPF, Windows10 (Mobile,Desktop etc.) uygulama geliştirme ile uğraşan arkadaşlar bilirler ki arayüz tarafında XAML (Extensible Application Markup Language) kullanılır ve codebehind'dan yani C# tarafından uygulama ekranında bulunan herhangi bir UI Control'ünün değeri değiştirme işlemlerini sık sık yaparız. İşte bu gibi işlemleri örneğin TextBlock'un Text'ini değiştirme işlemini C# tarafında tblName.Text="Caner"; yazmak yerine INotifyPropertyChanged interface'ini kullanarak bu gibi işlemleri kolaylıkla ve daha yönetilebilir bir şekilde yapabiliriz. (Tabi sadece TextBlock için geçerli değil, Button'un click event'i gibi durumlarda da INotifyPropertyChanged'İ kullanabiliriz)

INotifyPropertyChanged nedir dersek kısaca şöyle tanımlayabiliriz ;

"C# tarafında yani CodeBehind da tanımlı olan bir class'ın property'sinin değeri değiştiğinde bu değişimden UI'ı yani XAML tarafını bilgilendirmesi" demektir.

 

 

 

Şöyle bir örneğimiz olsun; bir adet Windows Phone uygulaması ve ekranda 2 tane TextBox, 1 tane Button ve 1 tane de Label olsun. Kullanıcı bu 2 TextBox'a birer sayı girecek ve Button'a tıkladığında hemen altında bulunan Label'da bu iki sayının toplamını yazacak.

 

 

HesaplaViewModel.cs class

MVVM pattern ile daha önce uğraşan arkadaşlar bilirler hiyerarşi Model, View, ViewModel diye ayrılır. Bizim uygulamamızda şuan Model yok ancak MainPage.xaml View'i ve hemen aşağıda bulunan ViewModel class'ımız var. Bu class View'imizin DataContext'i olacak ve UI tarafı ile bütün haberleşme bu class üzerinden gerçekleşecektir. ViewModel içerisinde tanımlı olan parametreleri UI'a DataContext üzerinden Binding işlemleri yapıp propertChanged anından UI thread'den durumu haberdar edip Bind olduğu UI Control' deki değerini update edecektir veya bir event ise o event'in davranışına göre çalışacaktır.  

  public class HesaplaViewModel : INotifyPropertyChanged
    {
        private ICommand _HesaplaCommand;
        private int _ilkSayi;
        private int _ikinciSayi;
        private int _sonuc;

        public HesaplaViewModel()
        {
            HesaplaCommand = new RelayCommand(Sum);
        }

        public int İlkSayi
        {
            get { return _ilkSayi; }
            set
            {
                _ilkSayi = value;
                OnPropertyChanged("İlkSayi");
            }
        }

        public int İkinciSayi
        {
            get { return _ikinciSayi; }
            set
            {
                _ikinciSayi = value;
                OnPropertyChanged("İkinciSayi");
            }
        }

        public int Sonuc
        {
            get { return _sonuc; }
            set
            {
                _sonuc = value;
                OnPropertyChanged("Sonuc");
            }
        }

        public ICommand HesaplaCommand
        {
            get { return _HesaplaCommand; }
            private set
            {
                _HesaplaCommand = value;
                OnPropertyChanged("HesaplaCommand");
            }
        }

        private void Sum(object obj)
        {
            Sonuc = İlkSayi + İkinciSayi;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

 

RelayCommand.cs class

RelayCommand button'a tıklandığında çalışacak olan event gibi düşünebiliriz, Butonun click statelerini aşağıda ki metodlar sayesinde handle edip yönetimini sağlıyoruz

    public class RelayCommand : ICommand
    {
        private Action<object> _action;
        public RelayCommand(Action<object> action)
        {
            _action = action;
        }
        public bool CanExecute(object parameter)
        {
            return true;
        }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
            _action(parameter);
        }
    }

 

App.xaml 

Burda HesaplaViewModel'ini Resource olarak tanımlama işlemini yapıyoruz.

<Application
    x:Class="App1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1">
    <Application.Resources>
        <local:HesaplaViewModel x:Key="HesaplaViewModel" />
    </Application.Resources>
</Application>

 

MainPage.xaml View'ı

App.xaml de tanımlaış olduğumuz Resource'u DataContext = "{StaticResource HesaplaViewModel}" olarak View'imize verip Binding işlemlerini yapacağız.

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    DataContext="{StaticResource HesaplaViewModel}">

    <Grid>
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
            <TextBox Grid.Row="0" Text="{Binding İlkSayi,Mode=TwoWay}" PlaceholderText="İlk Sayı" Width="200" HorizontalAlignment="Left"/>
            <TextBox Grid.Row="1" Text="{Binding İkinciSayi,Mode=TwoWay}" PlaceholderText="İkinci Sayı" Width="200" HorizontalAlignment="Left"/>
            <Button Grid.Row="2" Content="Hesapla" Width="200" Command="{Binding HesaplaCommand}" />
            <StackPanel Orientation="Horizontal" Grid.Row="3">
                <TextBlock Text="Sonuç : " FontSize="20"/>
                <TextBlock Text="{Binding Sonuc,Mode=TwoWay}" FontSize="20"/>
            </StackPanel>
        </Grid>
    </Grid>
</Page>

 

OnPropertyChanged() metoduna parametre olarak string bir değer almakta. Bu değer propertychanged anında hangi değerin değiştiğini anlamak için bir nevi ID ye benzer bir string değer veriyoruz ve ilgili property'nin değerinin update olma anında hangi property ise bu string parametrelere bakrak anlayabiliriz. Ama bu parametreyi vermek zorunda da değiliz eğer OnPropertyChanged() metodunu bu şekilde kullanırsak da otomatik olarak proeprty'nin ismini alacaktır.

 

Sonuç olarak ise hesapla butonuna tıklandığında çıktı şu şekilde olacaktır.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Görüldüğü üzre yazımızın başında bahsettiğimiz gibi code behind da tblName.Text="Caner";  gibi bir işlem yapmayıp bunu yerine INotifyPropertyChanged interface'inden faydalanıp işlemlerimizi öyle yaptık. Bu bize ne katar dersek, büyük çaplı projelerde genellikle MVVM pattern'i kullanılır ve INotifyPropertyChanged de bu pattern'in ayrılmaz bir parçasıdır. Bu şekilde yazdığımız kod hem daha "kaliteli"(tırnak içinde) hemde daha yönetilebilir oldu. Yarın bir gün dendi ki aynı işlevi yapan bir WPF app geliştirelim. Bu gibi bir durum için yazmış olduğumuz HesaplaViewModel'ini aynen olduğu gibi tek bir satır bile değiştirmeden referans olarak verilen ilgili proje içinde kullanabilir ve böylece çok büyük bir yazılım maliyetinden de kurtulmuş oluruz.

 

Pingbacks and trackbacks (2)+

Add comment