Makale Özeti

Makale dizimizin bu bölümünde daha önceden çeşitli metodlar, interface'ler kullanarak kendi isteklerimiz doğrultusunda bir Collectionu nasıl kişiselleştirebileceğimizi inceledik. Yapmış olduğumuz test sonucunda DataGrid'den direkt veri girişi veya silme gibi işlemlerin yapılamadığını saptamıştık. Şimdi ise bu problemi çözmek için gerekli kod yapısını ve implement etmemiz gereken interface olan IBindingList inteface'inin metodlarını inceleyelim. Bu interface metodları sayesinde Datagrid'de sorting işlemide yapabiliyor olacağız.

Makale

         Merhabalar,

         Makale dizimizin bu bölümünde daha önceden çeşitli metodlar, interface'ler kullanarak kendi isteklerimiz doğrultusunda bir Collectionu nasıl kişiselleştirebileceğimizi inceledik. Yapmış olduğumuz test sonucunda DataGrid'den direkt veri girişi veya silme gibi işlemlerin yapılamadığını saptamıştık. Şimdi ise bu problemi çözmek için gerekli kod yapısını ve implement etmemiz gereken interface olan IBindingList inteface'inin metodlarını inceleyelim. Bu interface metodları sayesinde Datagrid'de sorting işlemide yapabiliyor olacağız.

            #region IBindingList Members
            private bool mIsSorted = false;
            private ListSortDirection mSortDirection = ListSortDirection.Ascending;
            private PropertyDescriptor mSortProperty = null;

          Interface imizi implemet etmeye başladığımızda verilerin sort edilip edilmediğini tutacağımız değişken olan mIsSorted memer değişkenini, Sorting işleminin artanmı yoksa azalanmı sırada yapılacağını saklayacağımız member olan msortDirection değişkenini ListSortDirection tipinden vede hangi property'e göre sort edileceğini saklayacağımız member değişken olan mSortProperty değişkenini PropertyDescriptor tipinden tanımlıyoruz.

            public bool IsSorted
            {
                  get { return mIsSorted; }
            }
            public ListSortDirection SortDirection
            {
                  get { return mSortDirection; }
            }
            public PropertyDescriptor SortProperty
            {
                  get { return mSortProperty; }
            }

         Biraz önce tanımladığımız member değişkenleri encapsule edeceğimiz ReadOnly propertylerimizi tanımlıyoruz.

            public void AddIndex(PropertyDescriptor property)
            {
                  mIsSorted = true;
                  mSortProperty = property;
            }

         AddIndex metodunda sıralama yapılacak propertymizi belirliyoruz ve artık collectionumuzun sıralı olduğunu saklayacağımız mIsSorted değişkenimizin değerini true yapıyoruz.

            public object AddNew()
            {
                  object obj = typeof(T).GetConstructor(new Type[] { }).Invoke(null);
                  InnerList.Add(obj);
                  return obj;
            }

          AddNew metodumuz DataDrid'e yeni bir satır eklendiğinde devreye girecek olan metoddur. Bu metodun içeriğinde Generic Tipimiz olan T tipinin Constructorunu parametresiz olarak çağırarak bir nesne referansı oluşturuyoruz. Oluşturduğumuz bu referansı verileri sakladığımız değişken olan InnerList değişkenine atıyoruz.

            public bool AllowEdit
            {
                  get { return true; }
            }
            public bool AllowNew
            {
                  get { return true ; }
            }
            public bool AllowRemove
            {
                  get { return true; }
            }

          Burada implement edilen metodlar isimlerinden anlaşılabileceği gibi mevcut bir kaydın güncelenmesine, yeni bir kayıt eklenmesine veya kayıt silinmesine Datanın gösterildiği kontrol tarafından izin verilip verilmeyeceğini belirlediğimiz ReadOnly property'lerdir.

            public bool SupportsChangeNotification
            {
                  get { return true; }
            }
            public bool SupportsSearching
            {
                  get { return true; }
            }
            public bool SupportsSorting
            {
                  get { return true; }
            }

          Bu propertylerde adlarından anlaşılacağı gibi collectionumuzun Değişiklikleri bildirip bildirmeyeceğinin, içinde arama yapılıp yapılamayacağının ve dataların sıralanıp sıralanmayacağının okunduğu propertylerdir.

            public event ListChangedEventHandler ListChanged;
            event ListChangedEventHandler IBindingList.ListChanged
            {
                  add
                  {
                        ListChanged += value;
                  }
                  remove
                  {
                        ListChanged -= value;
                  }
            }
            protected virtual void OnListChanged(ListChangedEventArgs ev)
            {
                  if (ListChanged != null)
                  {
                        ListChanged(this, ev);
                  }
            }

          Bu kısımda ise ilk önce eventimizi ve EventHandler'ımızı tanımlıyoruz. Daha sonra eventimizin tetiklendiğinde çağıracağı metodu tanımlıyoruz.
 

            public int Find(PropertyDescriptor property, object key)
            {
                  foreach (T o in InnerList)
                  {
                        if (o.GetType().GetProperty(property.Name).GetValue(o, null) == key)
                        {
                              return InnerList.IndexOf(o);
                        }
                  }
                  return -1;
            }

          Find metodu adındanda anlaşılabileceği gibi bir propertysinin değeri belirlenen bir değere sahip olan nesneyi Collection içinden seçip çıkarmak için gereklidirç yapılan işlem ise Collection içindeki her nesnenin propertysinin aranan değere eşit olup olmadığının kontrol edilmesi ve eşitse o nesnenin collection içindeki indexinin geri döndürülmesidir.
 

            public void AddIndex(PropertyDescriptor property)
            {
                  mIsSorted = true;
                  mSortProperty = property;
            }

         AddIndex metodunda sıralama yapılacak propertymizi belirliyoruz ve artık collectionumuzun sıralı olduğunu saklayacağımız mIsSorted değişkenimizin değerini true yapıyoruz.

            public void RemoveIndex(PropertyDescriptor property)
            {
                  mSortProperty = null;
            }

          RemoveIndex metodunda ise sıralama yapacağımız propertylerimizi silebiliyoruz. Bu propertyleri silmek demek sıralama kriterlerimizi ortadan kaldırmak demektir.
 

            public void RemoveSort()
            {
                  mIsSorted = false;
                  mSortProperty = null;
            }          

          Sıralama işlemlerinin tümünü iptal edeceksek bu metodu çağırıyoruz. Sizinde gördüğünüz gibi bu metodda mSortProperty değişkenimiz sıfırlanıyor.
 

            public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
            {
                  mIsSorted = true;
                  mSortProperty = property;
                  mSortDirection = direction;
 
                  InnerList.Sort(new ObjectPropertyComparer(typeof(T), property.Name));
                  if (direction == ListSortDirection.Descending)
                        InnerList.Reverse();
            }
            #endregion

          ApplySort metodumuzda ise verilerimizin tutulduğu InnerList değişkenimizi sıralıyoruz. Ancak bunun için Collection içindeki nesnelerin sıralanması için belirli bir propertylerine göre birbirileri ile karşılaştırılması gereklidir. Bu karşılaştırmayı yapabilecek IComparer interface ini implement etmiş bir metoda gereksinim vardır. Objectleri propertylerine göre karşılaştırma yapabilecek Comparer class'ını kendimiz yazmamız gerekecek. Bu makalenin en sonunda bu classın yazılmasına dair kodları ve açıklamasını bulabileceksiniz. Bunun dışında yapılan işlem ise Descending(Azalan) bir sıralama yapılacak ise ilk önce Artan sıralama yapmak ve daha sonra collectiondaki nesnelerin sıralarını terse çevirmektir.

      public class ObjectPropertyComparer : IComparer
      {
            PropertyInfo _property;
            public ObjectPropertyComparer(Type objectType, string propertyName)
            {
                  MemberInfo[] members = objectType.GetMember(propertyName, MemberTypes.Property, BindingFlags.Instance | BindingFlags.Public);
                  if (1 != members.Length)
                  {
                        throw new ArgumentException(string.Format("Could not resolve the property name \"{0}\"!", propertyName), propertyName);
                  }
                  _property = (PropertyInfo)members[0];
            }
            public ObjectPropertyComparer(PropertyInfo property)
            {
                  if (null == property)
                  {
                        throw new ArgumentNullException("property");
                  }
                  _property = property;
            }
            public int Compare(object lhs, object rhs)
            {
                  object lhsValue = _property.GetValue(lhs, null);
                  object rhsValue = _property.GetValue(rhs, null);
                  int value = 0;
                  if (null != lhsValue)
                  {
                        value = ((IComparable)lhsValue).CompareTo(rhsValue);
                  }
                  else if (null != rhsValue)
                  {
                        value = ((IComparable)rhsValue).CompareTo(lhsValue);
                        value *= -1;
                  }
                  return value;
            }
      }

          Basit bir comparer olarak tasarlanan bu classta iki adet Ctor(Yapıcı Metod) ve bir adet metod bulunmaktadır. Yapıcı metodlar bizden nesneyi ve property adını alabileceği gibi direkt olarak propertyInfo'yuda alabilmektedir. Compare metodunda yapılan işlem ise verilen iki nesnenin Ctor da belirlenen propertylerindeki değerlerine göre karşılaştırılma yapılmasıdır.

          Bu makalede hepbirlikte komplex ir binding işleminin DataTable da oldugu gibi DataSette nasıl yapılabileceğini inceleyerek yazdığımız collectiona yeni bir özellik daha katmış olduk. Bundan sonraki makalede ise bu collectionun Web uygulamalarında saklanabilmesi veya web servislerinden geçirilebilmesi için serileştirme işleminin nasıl uygulanacağına dair olacaktır.

oztamer@hotmail.com
tamer.oz@yazgelistir.com
oztamer@hotmail.com
Ornek Kodlar