Makale Özeti

Çoğumuz küçük çapta kişisel veya büyük çapta kurulsal projelerimiz için gerek görsellik gerek se fonksiyonalite ve pratiklik adına bileşenler yazmaktayız. Bu bileşenlere örnek vermek gerekirse en basit olarak sadece rakam girilebilen nümeric textbox'ı gösterebiliriz. Kendi kişisel bileşenlerimizi yazmamızın yanı sıra bu işi profesyonel anlamda yapan Component firmalarından gerek web gerekse windows kontrolleri satın alabiliyoruz. Bu kontrollerin birçoğunda design zamanında developer'ın işini rahatlaştıracak bir Designer penceresi bulunuyor ve bu pencere kontrol üzerinden genellikle sağ tuş ile Run Designer dediğimizde açılıyor. İşte bu makalede inceleyeceğimiz temel konu böyle bir pencerenin nasıl yapılabileceğidir.

Makale

         Merhabalar,

         Çoğumuz küçük çapta kişisel veya büyük çapta kurulsal projelerimiz için gerek görsellik gerek se fonksiyonalite ve pratiklik adına bileşenler yazmaktayız. Bu bileşenlere örnek vermek gerekirse en basit olarak sadece rakam girilebilen nümeric textbox'ı gösterebiliriz. Kendi kişisel bileşenlerimizi yazmamızın yanı sıra bu işi profesyonel anlamda yapan Component firmalarından gerek web gerekse windows kontrolleri satın alabiliyoruz. Bu kontrollerin birçoğunda design zamanında developer'ın işini rahatlaştıracak bir Designer penceresi bulunuyor ve bu pencere kontrol üzerinden genellikle sağ tuş ile Run Designer dediğimizde açılıyor. İşte bu makalede inceleyeceğimiz temel konu böyle bir pencerenin nasıl yapılabileceğidir.

         Bu özelliğin yanı sıra Vİsual Studio 2005 ile gelen ve kontrolün sağ üstünde bunun ufak ok'a basılarak çok sık değiştirilen propertylere erişilen pencereyide benzer bir yöntemle kendimiz oluşturabilmekteyiz. Buda bu makale içinde incelenecek konulardan biridir.

         İsterseniz şimdi özelliklerimizi bileşenimize implement etmek için kodumuzu yazmaya başlayalım.

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
 
namespace DesignerApp
{
    [Designer(typeof(MyTextBoxDesigner))]
    public class MyTextBox : TextBox
    {
    }
}
         Bu kısımda yapmış olduğumuz tek şey MyTextBox isminde bir kontrolü TextBox class'ından inherit etmek ve attribute olarak [Designer(typeof(MyTextBoxDesigner))] eklemek. Bu eklediğimiz attribute sayesinde kontrolümüzün designer'ının MyTextBoxDesigner class'ı olacağını belirtiyoruz. İsterseniz şimdi bu class'ın nasıl yazıldığını inceleyelim.
 
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms.Design;
using System.ComponentModel.Design;
using System.ComponentModel;
 
namespace DesignerApp
{
    public class MyTextBoxDesigner : ControlDesigner
    {
        private DesignerActionListCollection actionLists;
        private DesignerVerbCollection insDesignerVerbCollection = new DesignerVerbCollection();
         Classımızda ilgili fonksiyonelliği kullanabilmek için ControlDesigner classından türetmemiz gerekmektedir. Tanımlamış olduğumuz private değişkenlerden bahsedelim. Burada actionList DesignerActionListCollection tipindendir ve kontrolün sağ üstündeki ok işareti sayesinde açılacak action listte gözükecek itemların belirlendiği yapıdır. insDesignerVerbCollection ise DesignerVerbCollection tipindendir ve sağ tuşta açılacak menüde bulunacak itemların belirlendiği yapıdır.

        public override DesignerVerbCollection Verbs
        {
            get
            {
                return insDesignerVerbCollection;
            }
        }
          Bu kısımda ise DesignerVerbCollection propertysini override ederek get metodunda kendi DesignerVerbCollection'umuzu döndürmesini sağlıyoruz. Visual Studio Designerinin sağ tuş tıklandığında çağırdığı property burasıdır.

        public MyTextBoxDesigner()
        {
            insDesignerVerbCollection.Add(new DesignerVerb("Arkaplan Rengini Degistir.", new EventHandler(ChangeBackgroundColor)));
        }
        public void ChangeBackgroundColor(Object sender, EventArgs e)
        {
            frmDesigner insFrmDesigner = new frmDesigner((MyTextBox)this.Control);
            insFrmDesigner.ShowDialog();
        }
         Designer'ın belirlendiği bu classımızın constructor'unda DesignerVerbCollection tipinden olan ve bir collection taşıyan değişkenimize. İsmi Arka Plan Rengini Degistir olan ve ChangeBackgroundColor metodunu gösteren bir eventhandler ekliyoruz. Daha sonrasında ChangeBackgroundColor metodunda ise olusturduğumuz ve tipi frmDesigner olan formumuzunu constructoruna kontrolümüzü parametre olarak vererek açıyoruz. Bundan sonra degisner desteği için gereken işlemlerimizi bu form üzerinde yapacağız. Şimdi ise action list i kullanabilmek için yazmamız gerekli olan kodu inceleyelim.

        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (null == actionLists)
                {
                    actionLists = new DesignerActionListCollection();
                    actionLists.Add(
                        new MyTextBoxDesignerActionList(this.Component));
                }
                return actionLists;
            }
        }
    }
}
          Bu classımızın DesignerActionListCollection propertysi ise Visual Studio nun bu kontrol için varolan Actionlisti arayacağı propertydir. Bizde bu kısımda kendi Designer Action list nesnemizi içine MyTextBoxDesignerActionList adında biraz aşağıda bahsedeceğimiz, Action List Classımızı Veriyoruz.

         Şimdi ise MyTextBoxDesignerActionList classımızı yazalım.
 
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Drawing;
 
namespace DesignerApp
{
    public class MyTextBoxDesignerActionList : DesignerActionList
    {
        MyTextBox mtb = null;
        DesignerActionUIService designerAction;
        public MyTextBoxDesignerActionList(IComponent component)
            : base(component)
        {
            this.mtb = component as MyTextBox;
            this.designerAction =GetService(typeof(DesignerActionUIService)) as DesignerActionUIService;
        }
        public void ArkaPlaniKirmiziYap()
        {
            GetPropertyByName("BackColor").SetValue(mtb, System.Drawing.Color.Red);
        }       
        public Color BackColor
        {
            get { return (Color)GetPropertyByName("BackColor").GetValue(mtb); }
            set { GetPropertyByName("BackColor").SetValue(mtb, value); }
        }
        private PropertyDescriptor GetPropertyByName(String propName)
        {
            PropertyDescriptor prop;
            prop = TypeDescriptor.GetProperties(mtb)[propName];
            if (null == prop)
                throw new ArgumentException("Property Bulunamadi",propName);
            else
                return prop;
        }
    }
}
          Bu class ımızı DesignerActionList'ten türetiyoruz ve prıvate değişkenler olarak Kontrolümüzü ve DesignerActionUıService nesnemizi tanımlıyoruz. Daha Sonrasında Constructorda parametrik olarak gelen componenti kendi component değişkenimize atıyoruz ve designerAction Nesnemizi oluşturuyoruz. En aşağıda bulunan GetPropertyByName metodu ise bize set edeceğimiz propertye erişebilmemiz için PropertyDescriptor nesnesini döndürmektedir. Daha sonrasında bizim bu class icine yazdıgımız her void designerda Action List kısmında gözükecektir. Yapamamız gereken ise bu metodun içinde ilgili property'e erişip SetValue metodu ile o property'e değer atamaktır. ArkaPlaniKirmiziYap metodundada bu işlem yapılmıştır. Bir diğer özellik ise propertyler sayesinde işlem yapmaktır. Bu class içine yazacağınız her property size action list tarafında uygun bir arayüzle gösterilecektir. Bu Classımızda BackColor propertysi bize action listte bir color diyalog ile gösterilecek ve değerleri değiştirebilmemiz sağlanacaktır. En son hali ise aşağıda gözüktüğü gibi olacaktır.



         Şimdi ise Designerda propertynin set edilmesi için gerekli formumuz olan frmDesigner'i yazalım.Bu forma kontrolümüz üzerinden aşağıdaki şekilde erişilecektir.
 
          Formumuzun dizaynı ise bir adet combobox ve bir labeldan oluşacaktır.



          Bu noktadan sonra tek yapmamız gereken Formumuzun Constructorunda kontrolümüzü parametre olarak alıp bunu bir değişkende saklamak ve ComboBox'ın SelectedValueChanged Eventında bu kontrolün ilgili property'sini değiştirmektir. Buna dair örnek kod aşağıda verilmiştir.
    public partial class frmDesigner : Form
    {
        private MyTextBox ctrl;
        public frmDesigner(MyTextBox tb)
        {
            InitializeComponent();
            ctrl = tb;
        }
 
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ctrl.BackColor = System.Drawing.Color.FromName(((string)comboBox1.SelectedItem));
        }
    }
         
         Sizinde görmüş olduğunuz gibi esasında birçoğumuzun aklında bulunan designerda nasıl pencere açılıyor gibi soruların cevaı esasında çok basit, tüm iş ilgili class içine property yazmaktan geçiyor. Bu sayede kendi yazdığınız bileşenlerin kişisel veya en çok kullanılan propertylerine çok rakatlıkla erişmek ve form dizaynında hızlanıp zaman kazanmak mümkündür.

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