Custom Control Oluşturmak 1: Otomatik Progress Bar

Merhaba dostlar.

Uzun zamandır yazmak istediğim bir konuydu bu aslında. Kısmet bugüneymiş. C#.NET ile Windows uygulaması geliştirirken; bazen, “yahu şöyle bir kontrol olsaydı ne de güzel olurdu” dediğimiz olmuştur. İşte bu cümleyi sarf ettiğiniz anda, Custom Control kavramı devreye girer ve bize “kendi kontrolünü kendin yap” der. Bunu yapabilmemiz için de, bize birkaç farklı seçenek sunar.

Bu seçenekler tamamen, custom control’ü ne için kullanacağımla ilgilidir. Genel olarak bu seçenekleri üçe ayırabiliriz:

User Control : Var olan kontrolleri bir araya getirerek yeni kontroller üretmemizi sağlayan tekniktir. Örneğin, kullanıcı giriş ekranını tasarlamak amacıyla,her seferinde tek tek iki Label iki TextBox bir Button kontrolü atmak yerine tüm bunları bir araya getirerek tek bir kontrol gibi kullanabilirsiniz. Bu sayede daha az efor harcamış olursunuz.

Derived Control: Bu teknik ise, Control classından türemiş olan herhangi bir kontrolü miras alarak, o kontrolün üyelerini geliştirmek ya da değiştirmek suretiyle yeni bir kontrol sınıfı yaratmaktır. Örneğin bu teknikle, yalnızca sayısal değer içeren bir TextBox kontrolü yapabiliriz.

Owner-drawn Control: Bu seçenek ise, GDI+ kullanarak kendine has bir tasarımları olan kontroller yapmanızı sağlayacaktır.

Lafı çok uzatmadan, bir User Control örneği yapalım. Bu örnekte, kendi ProgressBar kontrolümüzü yapacağız. Bu progressbar asenkron işlemlerde kullanılabilecek türden bir kontrol olsun. Yalnız, belirtmem gereken nokta şu; bazı asenkron işlemlerin (örneğin web servislerinden sorgu çekmek ) ne zaman biteceği belli olmaz. Bu nedenle, kontrolümüzde belirli bir yüzde ifadesi göstermeyeceğiz. Yalnızca kullanıcıya “yükleniyor” uyarısı yapacak.

Öncelikle, standart bir Windows Application projesi açalım. Ardından da projeye sağ tık, Add New Item’dan User Control template’i seçerek, Progress.cs ismiyle ekleyelim:

 

 

Eklediğimiz UserControl’ün Design ekranını tasarlayacağımız kontrolün taşıyıcısı (container) olarak düşüneceğiz. Öyleyse, bu ekrana bir Timer bileşeni, bir ProgressBar ve bir de Label kontrolü atalım:

 

Kontrol Tipi

Adı

ProgressBar

Bar

Label

lblSonuc

Timer

Timer1

Tasarımı da hallettikten sonra koda geçebiliriz.

İlk önce, lblSonuc kontrolüne “Yükleniyor. . . ” uyarısı yapan metodu yazmakla işe başlayalım. Yalnız bu uyarı, kuru kuru bir yazı da olmasın. Asenkron işlem devam ettiği sürece, uyarı kelimesinin yanına “.” işareti gelerek küçük bir atraksiyon olsun (gerçi bu bile kuru ama olsun).

private void LabeliGuncelle()

{

lblSonuc.Text = “Yükleniyor”;

int sayi = Bar.Value % 5;

for (int i = 0; i < sayi ; i++)

{

lblSonuc.Text += “.”;

}

}

Tasarladığımız bu kontolün, belirsiz bir süre için çalışacağını daha önce belirtmiştim. Bu durumda, progressBar kontrolüm, maksimum değere ulaştıktan sonra eğer işlem bitmemişse tekrar başa dönmeli ve yine dolmaya başlamalı. Dolayısıyla kontrolü kullanırken, ProgressBar’ın saniyede ne kadar değer artacağını belirleyerek, bu dolma hızını ayarlayabilmeliyim. Yani dilersem, saniyede 10’ar 10’ar ya da 5’er 5’er artmasına karar verebilmeliyim. Bu nedenle kontrolüme SaniyeBaşınaYuzde isimli bir özellik ekliyorum.

int saniyeBasinaYuzde = 5;

public int SaniyeBasinaYuzde

{

get { return saniyeBasinaYuzde; }

set

{

//progressBar’ın değerinin artabilmesi için, bu özelliğin değeri 0’dan büyük olmak zorunda

if (value <= 0)

{

throw new ArgumentException(“Değer, 0 ya da daha küçük bir sayı olamaz”);

}

saniyeBasinaYuzde = value;

}

}

Kontrolümüzü çalıştıracak olan Başlat metodunu yapalım şimdi de:

public void Baslat()

{

Bar.Maximum = 200;

decimal step = Math.Round((decimal)Bar.Maximum * SaniyeBasinaYuzde / 1000);

Bar.Step = (int)step;

Bar.Value = 0;

timer1.Start();

}

UserControl’ün Başlat metodu çağırıldığında, Timer componenti çalışmya başlayacak. Ama, uygulamam çalışırken, bu kontrolü durdurmak istersem ne olacak? Madem öyle ona da bir metod yazalım:

public void Durdur()

{

timer1.Stop();

Bar.Value = 0;

}

Şimdi, gelelim başka bir senaryoya… UserControl’ümüz çalışırken, asenkron işlemimiz sonlandı. Yani işimiz bitti. Fakat bu esnada, ProgressBar’ımızın değeri, maksimumda olmayabilir değil mi? Yani asenkron işleminiz bitmiş ama sizin ProgressBar’ınız işin “bitmemiş” olduğunu gösteriyor. Bu durumda, program çalışırken istediğimiz zaman ProgressBar’ın değerinin maksimum olmasını sağlamam gerekir. İşte o nedenle bir metot daha yazıyoruz..

public void Bitir()

{

timer1.Stop();

Bar.Value = Bar.Maximum;

lblSonuc.Text = “Tamamlandı…”;

}

ProgressBarın ilerlemesini sağlayacak metodda sıra

public void Ilerle()

{

Bar.PerformStep();

LabeliGuncelle();

}

Ve son olarak, timer bileşeninin Tick olayı:

private void timer1_Tick(object sender, EventArgs e)

{

Ilerle();

if (Bar.Value==Bar.Maximum )

{

Bar.Value = 0;

}

}

Buraya kadar sorun yok. Artık, kontrolümüzü test etmemizin vakti geldi. Öncelikle UserControl’ümüzü Build edelim. Ardından uygulamamızın ana formunun design ekranına dönelim ve ToolBox’dan “Progress” isimli user kontrolü sürükleyip bırakalım

 

Uygulamamı test edebilmek için iki adet de buton atıyorum.

 

 

Kodları ise:

private void btnBaslat_Click(object sender, EventArgs e)

{

progress1.Baslat();

}

private void btnBitir_Click(object sender, EventArgs e)

{

progress1.Bitir();

}

…Ve çalıştırıyorum:

 

 

 

Evet.. Basit ve kullanışlı bir userControl oldu. Bir sonraki makalede görüşmek üzere

Öneri ve istek için: turkay@turkayukmez.com

Kendinize iyi bakın