.NET'te Dinamik Kontrol Oluşturma

Bu yazıda windows ve web uygulamalarında dinamik kontrollerin nasıl oluşturulacağını ve oluşturulan dinamik kontrollere erişim yöntemlerini inceleyceğiz. Ayrıca bu yazıda dinamik kontrol oluşturma ile ilgili kapsamlı bir örnek kod yeralmaktadır.

Bir çok uygulamada(özellikle oyunlarda) kontrollerimizin sayısını tasarım aşamasında bilemeyebiliriz. Örneğin hepimizin bildiği mayın tarlası oyununda, oyun alanı bir çok kareden oluşmaktadır. Üstelik oyun alanı, kullanıcının isteğine göre değişebilmektedir. Eğer tasarım aşamasında bütün kontroller form üzerine yerleştirilşmiş olsaydı hem bu kontrollerin yönetimi zorlaşacaktı hemde gereksiz yere bir çok kod yazılmış olacaktı. Buna benzer bir durum web formları ile programlama yaparken de görülebilir. Örneğin bir anket sisteminde anketin seçenekleri kadar CheckBox kontrolünü dinamik olarak web formunun üzerine yerleştirebilmemiz gerekir. Eğer bu imkanımız olmasaydı Web formları çok esnek bir programlama modeli sunmazdı. Neyse ki Microsoft tasarımcıları herşeyi düşünmüş... :)

Dinamik kontrol oluşturmaya geçmeden önce nasıl bir form tasarımı yapmaya çalıştığımıza bakalım. Aşağıdaki formdan da gördüğünüz üzere 8X8'lik bir dama tahtasının her bir karesi aslında bir Button kontrolünden ibarettir. Tasarım aşamasında 64 tane Button kontrolünü form üzerine yerleştirip herbirni tek tek düzenlemek yerine bir döngü vasıtası ile istediğimiz sayıda Button kontrolünü oluşturup Form elemanına ekleyeceğiz.



ToolBox penceresinde görüdüğünüz bütün kontrolleri temsil eden sınıflar System.Windows.Forms isim alanında bulunan Control isimli sınıftan türetilmiştir. Bazı kontroller ise yapısında değişik kontrolleri barındıracak şekilde tasarlanmıştır. Örneğin Form penceresi üzerene eklenen kontroller bu duruma bir örnektir. Kontrolleri gruplamak için kullanılan GrouopBox ta bu şekildedir. Bu özel kontrollere yeni bir kontrol eklemek için bu Control türünden olan Controls isimli koleksiyon kullanılmaktadır. Örneğin bir form üzerine yeni bir Button kontrolü eklemek için aşağıdaki deyimleri yazmalıyız.

Button tb = new Button();
Form1.Controls.Add(button)

Yukarıdaki deyimleri bir döngü içinde yapıp oluşturduğumuz Button kontrollerinin ilgili özelliklerini değiştirdikten sonra dama tahtasını rahatlıkla oluşturabiliriz.

Şimdi bu yazının en altında bulunan linki kullanarak projeyi bilgisayarınıza yükleyerek projeyi açın. Form1 sınıfının içinde bulunan aşağıdaki TahatCiz() isimli metodu inceleyerek kontrollerin dinamik olarak nasıl yaratıldıklarını inceleyin.

private void TahtaCiz(int Boyut1,int Boyut2, int En, int Boy)
{
    
int satir =0;
    
int sutun =0;

    Button tb =
new Button();

    
for(int i=0; i < Boyut1*Boyut2; i++)
    {

        if(i % Boyut2 == 0)
        {
            satir++;
            sutun = 0;
        }

        tb = new Button();
        tb.Name = "tb" + i.ToString();
        tb.TabIndex = i;
        tb.Text = i.ToString();
        tb.Size =
new System.Drawing.Size(En,Boy);

        Point p =
new System.Drawing.Point(tb.Size.Width + (sutun-1)*tb.Width,tb.Size.Height + (satir-2)*tb.Height);

        tb.Location = p;
        tb.FlatStyle = FlatStyle.Standard;
        tb.Click +=
new System.EventHandler(this.button1_Click);

        Butonlar.Add(tb);
       
 this.Controls.Add(tb);
        sutun++;
    }

         this.ClientSize = new Size(tb.Width*Boyut2 ,tb.Height*Boyut1);
        satir = 0;
        sutun = 0;
        Butonlar.TrimToSize();
        RenkAyarla();
}

TahtaCiz() isimli metodu biraz inceleyelim. Bu metot kendisine gönderilen bilgiler ışığında form üzerine dinamik bir dama tahtası çizmektedir. Ayrıca işe yarar bir kaç işlem daha yapmaktadır. Bu metoda gönderilen Boyut1 ve Boyut2 değişkenleri dama tahtasının boyutlarını belirtmektedir. En ve Boy parametreleri ise tahtadaki her bir karenin enini ve boyunu belirtmektedir. Bu bilgileri parametre olarak almamız istediğimiz boyutta dama tahtasını çizebileceğimiz anlamına gelmektedir. Zaten form üzerine konulan bir menü yardımıyla dama tahtasının boyutu ve karelerin en ve boyu istenildiği gibi değiştirilmektedir. Bu metot sadece butonların form üzerine yerleştirilmesinden sorumludur. RenkAyarla() isimli diğer bir metot ise yerleştirilen bu butonların bir algoritmaya göre renklerini ayarlamayı sağlamaktadır. Bu metot içinde oluşturulan buton kontrollerine başka metotlar içinde erişebilmek için oluşturulan her kontrol global düzeyde tanımlanan Butonlar isimli bir Arraylist koleksiyonuna eklenmektedir. Bu metottaki diğer önemli bir satır ise oluşturulan dama tahtasınının boyutlarına göre form nesnesinin yeniden şekillendirilmesidir. Bu işlem

this.ClientSize = new Size(tb.Width*Boyut2 ,tb.Height*Boyut1);

satırıyla yapılmaktadır.

Not: Her bir Button kontrolünün yanyana ve alt alta nasıl yerleştirildiğini daha iyi anlamak için size tavsiyem kağıt üzerine bir dama tahtası çizip her bir karenin konumuna ilişkin matematiksel bir ifade bulun. Böylece herşey daha açık olacaktır.

Aşağıdaki satırda her bir buton kontrolünün Text özelliği döngü değişkeni olan i'ye atanmaktadır.

tb.Text = i.ToString();

Dinamik kontrolleri oluşturma ile ilgili diğer bir önemli nokta da kontrollere ilişkin olayların nasıl çağrılacağıdır. Dikkat ederseniz yukarıdaki metotta oluşturulan bütün kontrollerin Click olayına EventHandler temsilcisi yardımıyla button1_Click() metodu iliştirilmiştir. Oluşturulan butonlardan herhangi birine tıkladığınızda bu metot işletilecektir. Peki hani butonun tıklandığını nasıl anlayacağız. Bunun için button1_Click() metodunun bildirimine bakalım.

private void button1_Click(object sender, System.EventArgs e)
{
    Button b = (Button)sender;

    MessageBox.Show(b.Text);
}

Yukarıdaki metodun bir parametresi olan sender değişkeni bu metodun hangi button'un tıklanması sonucu işletildiğini tutmaktadır. Bize bu imkanı sağlayan elbetteki EventHandler temsilcisidir(delegate).

Dönüşüm operatörü kullanılarak sender nesnesi Button nesnesine dönüştürülümektedir. (Bu işleme unboxing denildiğini de hatırlatmak isterim)

Bu durumda, örneğin üzerinde 39 yazan Button'a tıkladığınızda gösterilen mesaj kutusuna gibi 39 yazacaktır.

Aşağıdaki ekran görüntüsündeki dama tahtasının biçimi uygulamadaki Ayarlar menüsündeki Renk sekmesi tıklanarak oluşturulabilir.



Not: Dama tahtası biçiminde bir form oluşması için Renk Seçimi penceresindeki Gradyan Katsayısı ortalanmalıdır. Renk ayarlama işleminin nasıl yapıldığı bu yazı kapsamında olmadığı için detaylarını anlatmayacağım. RenkAyarla() isimli metodu incelemenizi tavsiye ediyorum.

Web formları ile dinamik kontrol oluşturmak yukarıda anlattıklarımdan farklı değil. Yeni bir ASP.NET uygulaması açarak aşağıdaki gibi bir form tasarlayın.
Dinamik olarak oluşturacağımız kontrolleri Page sınıfına akleyebileceğimiz gibi PlaceHolder kontrolünü de kullanabiliriz. Ben bu iş için PlaceHolder kontrolünü tercih ettim.



"Oluştur" isimli butonun Click olayına ilişkin metodunu aşağıdaki gibi değiştirip sonucu inceleyelim.

private void Button1_Click(object sender, System.EventArgs e)
{
    int Adet = Convert.ToInt32(TextBox1.Text);

    for(int i=0; i<Adet; ++i)
    {
        TextBox yeni =
new TextBox();
        yeni.ID = "Text" + i.ToString();
        yeni.Text = "TextBox" + i.ToString();

        PlaceHolder1.Controls.Add(yeni);
        PlaceHolder1.Controls.Add(
new LiteralControl("<br/>"));
    }
}

Projeyi derleyip çalıştırın ve TextBox kutusuna bir tamsayı girip "Oluştur" butonuna tıklayın. İşlermleri başarı ile yaptıysanız aşağıdaki gibi "PlaceHolder" kontrolü içinde 4 adet TextBox kontrolü dinamik olarak yerleştirilecektir.



Not : Sunucu kontrolü olmayan <br> etiketinin LiteralControl olarak tanımlandığına dikkat edin.

Dinamik kontrolleri oluşturmayı öğrendiğinize göre artık web tabanlı bir mayın tarlası oyunu yapmanın zamanı geldi sanırım :) Biraz çaba ile bu oyunu rahatlıkla yapabileceğinizi düşünüyorum.