Silverlight ile Veri Doğrulama – IDataErrorInfo

Standard

Kullanıcılar uygulamamıza veri girerken en çok dikkat etmemiz gereken şeylerden biri girilen verinin doğru olup olmadığını denetlemektir. Normalde bu doğrulamayı kendimiz teker teker girilen değerleri kontrol ederek gerçekleştiririz ve eğer girilen değerler doğru değilse bununla ilgili uyarıları ve/veya gerekli diğer işlemleri deyim yerindeyse “el ile” yaparız. Bu durum küçük miktarlarda veri girişinde sorun çıkarmasa da, eğer kullanıcıların çok miktarda veri girmesi gerekirse bir angarya haline gelerek gereksiz zaman ve enerji harcamamıza neden olabilir.

Bu tarz veri doğrulama işlemlerini TextBox yanına uyarıları içerecek olan görünmez TextBlock’lar koyup, veri her değiştiğinde kontrol ettikten sonra TextBlock’un görünürlüğünü ve TextBox’ın arkaplan rengini değiştirerek yapmaktansa, Silverlight uygulamamız içinde data binding ve IDataErrorInfo interface’ini kullanarak hem (aşağıdaki gibi) göze güzel gözüken bir şekilde, hem de daha kolay ve hızlı olarak gerçekleştirebiliriz. Bu yazımda, birlikte kullanıcı adı ve şifre kaydederken doğrulama yapan bir Silverlight uygulaması yazacağız.

O halde yeni bir Silverlight projesi açarak başlayalım. Ben projenin adını ValidationApplication koydum. Projeyi oluştur dedikten sonra açılan pencerede “Host the Silverlight application in a new Web site” seçiliyken OK diyerek devam edelim.

MainPage.xaml içerisinde aşağıdaki şekilde kullanıcı adı için bir TextBox, şifre için bir PasswordBox, ve bir de Button yerleştirelim. Yapmak istediğimiz şey, kullanıcı adı ve şifre belirli kurallara uymadığı sürece kaydet düğmesine basılamaması ve kullanıcı adı ve/veya şifre yanlış olduğunda neyin yanlış olduğuna dair kullanıcıya hem uyarı, hem de açıklama gösterilmesi.

Sıradaki adımımız, data binding kullanacağımız için kullanıcı adı ve şifreye karşılık gelecek (ve daha sonra IDataErrorInfo interface’ini kullanacak) bir sınıf oluşturmak. MainPage.xaml.cs dosyası içinde UserInfo sınıfımızı aşağıdaki şekilde oluşturuyoruz:

    public class UserInfo
    {
        private string _kullaniciAdi;
        private string _sifre;

        public string kullaniciAdi
        {
            get
            {
                return _kullaniciAdi;
            }
            set
            {
                _kullaniciAdi = value;
            }
        }

        public string sifre
        {
            get
            {
                return _sifre;
            }
            set
            {
                _sifre = value;
            }
        }
    }

Şimdi UserInfo sınıfımıza IDataErrorInfo interface’ini eklemeliyiz. IDataErrorInfo, temelde bize istediğimiz özel veri doğrulama kurallarını koymamızı ve bu kurallara göre istediğimiz şekilde uyarı göstermemizi otomatik olarak sağlayan bir interface. Sınıfımıza aşağıdaki gibi eklemeler yapıyoruz:

    public class UserInfo : System.ComponentModel.IDataErrorInfo, System.ComponentModel.INotifyPropertyChanged
    {
        private string _kullaniciAdi;
        private string _sifre;

        public string kullaniciAdi
        {
            get
            {
                return _kullaniciAdi;
            }
            set
            {
                _kullaniciAdi = value;
                this.RaisePropertyChanged("kullaniciAdi");
            }
        }

        public string sifre
        {
            get
            {
                this.RaisePropertyChanged("sifre");
                return _sifre;
            }
            set
            {
                _sifre = value;
            }
        }

        public string Error { get; set; }

        public string this[string columnName]
        {
            get
            {
                string error = string.Empty;
                switch (columnName)
                {
                    case "kullaniciAdi":
                        {
                            break;
                        }
                    case "sifre":
                        {
                            break;
                        }
                }
                return error;
            }
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged(string propertyName)
        {
            if ((PropertyChanged != null))
            {
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }

Bu şekilde sınıfımıza IDataErrorInfo ve onun çalışması için gerekli olan INotifyPropertyChanged interface’lerini uyguladık. Şimdi, “public string this[string columnName]” içindeki switch ifadesini doldurarak doğrulama kurallarını belirleyeceğiz.

Şu şekilde doğrulama yapalım: Kullanıcı adı boş olmasın. Şifre boş olmasın, en az 6 karakter olsun, ve “password” olmasın.

Switch ifadesini bu kuralları yansıtacak şekilde aşağıdaki gibi dolduruyoruz:

                switch (columnName)
                {
                    case "kullaniciAdi":
                        {
                            if (String.IsNullOrEmpty(kullaniciAdi))
                            {
                                error = "Kullanıcı adı boş olamaz.";
                            }
                            break;
                        }
                    case "sifre":
                        {
                            if (String.IsNullOrEmpty(sifre))
                            {
                                error = "Şifre boş olamaz.";
                            }
                            else if (sifre.Length < 6)
                            {
                                error = "Şifre en az 6 karakter olmalıdır.";
                            }
                            else if (sifre == "password")
                            {
                                error = "Daha güçlü bir şifre seçin.";
                            }
                            break;
                        }
                }

Gördüğünüz üzere istediğimiz koşula istediğimiz uyarıyı verebiliyoruz. Sınıfımızı ayarladığımıza göre sıra data binding yapmaya geldi. Öncelikle aşağıdaki kodları ekliyoruz:

    public partial class MainPage : UserControl
    {
        UserInfo userInfo;
        int errorsOnPage;

        public MainPage()
        {
            InitializeComponent();

            errorsOnPage = 0;

            userInfo = new UserInfo();
            LayoutRoot.DataContext = userInfo;
        }
    }

Burada boş bir UserInfo sınıfı oluşturduk ve ardından bunu LayoutRoot’un DataContext’i olarak belirledik. Normalde kullanıcı adı ve şifrenin olacağı TextBox’ları bir Grid içerisine alarak bu Grid’in DataContext’ini ayarlamamız gerekirdi, ancak örnek olduğu için bu şekilde gerçekleştirdim. Burada tanımladığımız (ve 0 olarak initialize ettiğimiz) errorsOnPage değişkenini biraz daha ileride kullanacağız.

Doğrulama yapmaya başlamamız için yapacağımız son ekleme kullanıcı adı ve şifreyi aldığımız kontrollerin Text (ve Password) özelliklerini aşağıdaki gibi bind etmek:

        <TextBox x:Name="kullaniciAdiTextBox" Text="{Binding kullaniciAdi, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" HorizontalAlignment="Left" Height="23" Margin="105,75,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <PasswordBox x:Name="sifrePasswordBox" Password="{Binding sifre, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" HorizontalAlignment="Left" Margin="105,113,0,0" VerticalAlignment="Top" Width="120"/>

Eğer uygulamayı şimdi çalıştırırsanız, veri doğrulamanın gerçekleştiğini görürsünüz. 🙂

Geriye eklememiz gereken iki şey kaldı. Birincisi, eğer uygulamayı çalıştırdıysanız doğrulamanın siz o kontrolden ayrıldığınız anda yapıldığını görmüşsünüzdür. Bunu düzelterek sürekli denetlemek isteyebiliriz. İkincisi ise, hata olduğu zaman kaydet düğmesini devre dışı bırakmalıyız.

İlkini yapmak için, kullanıcı adı aldığımız TextBox’ın TextChanged, şifre aldığımız PasswordBox’ın da PasswordChanged eventlerini aşağıdaki gibi doldurmalıyız:

using System.Windows.Data;
        private void kullaniciAdiTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            BindingExpression bindingExpression = kullaniciAdiTextBox.GetBindingExpression(TextBox.TextProperty);
            bindingExpression.UpdateSource();
        }

        private void sifrePasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
        {
            BindingExpression bindingExpression = sifrePasswordBox.GetBindingExpression(PasswordBox.PasswordProperty);
            bindingExpression.UpdateSource();
        }

Bu sayede kullanıcı adı ve şifre girişinde her değişimde doğrulama tekrarlanacaktır. Son olarak, kaydet düğmesini hata varken devre dışı bırakmak için, errorsOnPage global değişkenini kullanıp, LayoutRoot’un BindingValidationError eventini aşağıdaki gibi doldurarak uygulamamızı sonlandırıyoruz:

        private void LayoutRoot_BindingValidationError(object sender, ValidationErrorEventArgs e)
        {
            switch (e.Action)
            {
                case ValidationErrorEventAction.Added:
                    errorsOnPage++;
                    break;
                case ValidationErrorEventAction.Removed:
                    errorsOnPage--;
                    break;
            }
            if (errorsOnPage == 0)
                kaydetButton.IsEnabled = true;
            else
                kaydetButton.IsEnabled = false;
        }

Uygulamayı çalıştırdığımızda artık istediğimiz şekilde çalıştığını görüyoruz. 🙂

Bu şekilde veri doğrulamanın başka bir artısı ise, eğer aynı veriyi (ya da aynı sınıfın başka üyelerini) başka bir yerde tekrar doğrulamamız gerekiyorsa, sadece XAML kontrollerinin data bindingini düzenleyerek aynı kodu kullanabiliyoruz. Özellikle çok miktarda veri girilen yerlerde IDataErrorInfo çok faydalı olabilir.

Uygulamanın kaynak koduna buradan ulaşabilirsiniz.

Gelecek yazılarımda görüşmek üzere. 🙂

Advertisements

Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s