SİTE
İÇİ ARAMA |
|
|
Blogroll |
|
|
|
|
|
|
Web Server Control Yazmak - 2 |
|
| Gönderiliyor lütfen bekleyin... |
|
|
Bir önceki
makalemizde
web sunucu kontrollerini nasıl geliştireceğimizi incelemeye başlamıştık.
Bu günkü makalemizde, ViewState’ lerin web sunucu kontrollerinde nasıl
ele alınabileceğinden ve kontrollerin tasarım zamanındaki (design time) yeteneklerinin
nitelikler (attributes) yardımıyla nasıl arttırılabileceğinden
bahsetmeye çalışacağız.
Herhangibir web sunucu kontrolünün (web
server control) bazı
özellikleri (properties) sayfa üretilirken belirlenmek (set) istenebilir. Bu
işlem için sayfanın Page_Load olay (event) metodu ideal bir noktadır. Hatta
burada sayfanın Postback edilip edilmediği kontrol edilerek,
özelliklerin sadece sayfanın ilk yüklenişinde belirlenmesi
sağlanabilir. Ancak burada ViewState kullanılmadığı takdirde
karşılaşılabilecek önemli bir problem vardır. Bu problemi analiz
edebilmek için, bir önceki makalemizde geliştirdiğimiz TarihKontrolum
isimli bileşenimize üç yeni özellik daha ekleyerek analizimize
başlayalım. Bu özellikler ile
liste kutularındaki gün, ay, yıl bilgilerinin değerlerini değiştirmeyi
ve elde etmeyi hedeflemekteyiz.
private string
_seciliGun;
private string _seciliAy;
private string _seciliYil;
public string SeciliGun
{
get{return _seciliGun;}
set { _seciliGun = value; }
}
public string SeciliAy
{
get{return _seciliAy;}
set { _seciliAy= value; }
}
public string SeciliYil
{
get{ return _seciliYil; }
set { _seciliYil= value; }
} |
Çok doğal olarak web sunucu
kontrolümüze ilişkin Render metodu içerisinde de bazı
değişiklikler yapmalıyız. Nitekim sayfa yüklenirken belirlenen gün, ay
ve yıl değerlerinin, render edilen HTML içeriğine selected niteliği
olarak aktarılması gerekmektedir. Bu nedenle Render metodu içerisinde,
özelliğin o anki değeri ile for döngüsü içerisindeki değerler
karşılaştırılmış ve eşleşme olması halinde, ekrana basılacak olan
option elementinin yapısı değiştirilmiştir.
protected
override void Render(HtmlTextWriter writer)
{
writer.Write("<span id=’lblGun’>" + GunMetin + "</span>");
writer.Write(" ");
writer.Write("<select name=’Gun’ id=’Gun’>");
for (int i = 1; i <= 31; i++)
{
if (SeciliGun ==
i.ToString())
writer.Write("<option selected=’selected’ value=’" +
i.ToString() + "’>" + i.ToString() + "</option>");
else
writer.Write("<option value=’" + i.ToString() + "’>" +
i.ToString() + "</option>");
}
writer.Write("</select>");
writer.Write(" ");
writer.Write("<span id=’lblAy’>" + AyMetin + "</span>");
writer.Write(" ");
writer.Write("<select name=’Ay’ id=’Ay’>");
for (int i = 1; i <= 12; i++)
{
if (SeciliAy
== i.ToString())
writer.Write("<option selected=’selected’ value=’" +
i.ToString() + "’>" + i.ToString() + "</option>");
else
writer.Write("<option value=’" + i.ToString() + "’>" +
i.ToString() + "</option>");
}
writer.Write("</select>");
writer.Write(" ");
writer.Write("<span id=’lblYil’>" + YilMetin + "</span>");
writer.Write(" ");
writer.Write("<select name=’Yil’ id=’Yil’>");
for (int i = 1950; i <= 2050; i++)
{
if
(SeciliYil == i.ToString())
writer.Write("<option selected=’selected’ value=’" +
i.ToString() + "’>" + i.ToString() + "</option>");
else
writer.Write("<option value=’" + i.ToString() + "’>" +
i.ToString() + "</option>");
}
writer.Write("</select>");
base.Render(writer);
} |
Dikkat ederseniz, özelliklerimizin
değerlerini, for döngüleri içerisinde yakalıyoruz ve buna göre option
elementine selected niteliğini (attribute) ekliyoruz. Peki, kontrolümüzü bu
son haliyele sayfamızda kullandığımızda ve sayfanın Load olay metodunda
aşağıdaki kodları yazdığımızda neler olacaktır?
protected void
Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
TarihKontrolumOld1.SeciliGun
= "3";
TarihKontrolumOld1.SeciliAy
= "4";
TarihKontrolumOld1.SeciliYil
= "2008";
}
} |
Load olay metodu içerisind, eğer sayfa
ilk kez yükleniyorsa (ki bu kontrolü IsPostBack özelliğinin değerine
bakarak yapıyoruz), web sunucu kontrolümüzün ilgili özelliklerine bazı
başlangıç değerleri set edilmektedir.

Ancak sayfayı tekrardan sunucuya
gönderdiğimizde, IsPostBack kontrolü nedeni ile if bloğu içerisindeki
kodlar bir kez daha çalıştırılmayacaktır. Bu nedenlede sayfanın bir sonraki talep
(request)
için çıktısı aşağıdaki gibi olacaktır. Dikkat ederseniz, SeciliGun,
SeciliAy ve SeciliYil özellikleri başlangıç değerlerine göre yeniden
belirlenmiştir. (Bu durum, kontrolün her sayfa istediğinde yeniden
örneklenişinin ve ilk değerlerin atanışının doğal bir sonucu olarak
düşünülebilir.)

Aslında sorun, istemci (client) ile sunucu(server)
arasında web sunucu kontrolü içerisindeki verilerin (data) taşınmıyor
oluşudur. Bu amaçla bildiğiniz gibi Asp.Net uygulamalarında ViewState’ lerden faydalanabiliriz.
ViewState’ ler sunucu tarafından yeniden üretilen, sayfalar içerisindeki
verileri saklamak amacıyla istemci tarafındaki çıktıya ilave edilen
gizli alanlardır (hidden field). Bu alanın içeriği string bazlıdır. Dikkat edilmesi
gereken noktalardan birisi, ViewState’ in içerisinde çok yüksek boyutlu
veri taşımasının, üretilecek olan HTML içeriğini fazlasıyla şişirecek
olmasıdır. Bu nedenle ViewState içerisine veri atarken çoğunlukla string
tipine dönüştürülebilen ve çok yüksek boyut içermeyen bilgileri ele
almakta fayda vardır. TarihKontrolum isimli bileşenimiz içerisinde
GunMetin, AyMetin, YilMetin, SeciliGun, SeciliAy, SeciliYil
özelliklerinin içeriklerini ViewState içerisinde saklayabiliriz. Böylece
yukarıdaki modele göre sayfanın ilk üretilişinde hazırlanan veri içeriği
istemci tarafındaki çıktı içerisinde yer alan gizli alana ilave
edilecektir. Bu ihtiyacı cevaplandırabilmek amacıyla, TarihKontrolum
bileşeninde aşağıdaki değişiklikleri yapmamız yeterli olacaktır.

public class
TarihKontrolum:Control
{
public string GunMetin
{
get {
if (ViewState["gunMetin"]
!= null)
return
ViewState["gunMetin"].ToString();
else
return "Gün";
}
set {
ViewState["gunMetin"] = value;
}
}
public string AyMetin
{
get
{
if (ViewState["ayMetin"]
!= null)
return
ViewState["ayMetin"].ToString();
else
return "Ay";
}
set {
ViewState["ayMetin"] = value;
}
}
public string YilMetin
{
get
{
if (ViewState["yilMetin"]
!= null)
return
ViewState["yilMetin"].ToString();
else
return "Yıl";
}
set {
ViewState["yilMetin"] = value;
}
}
public string SeciliGun
{
get
{
if (ViewState["seciliGun"]
!= null)
return
ViewState["seciliGun"].ToString();
else
return "";
}
set {
ViewState["seciliGun"] = value;
}
}
public string SeciliAy
{
get
{
if (ViewState["seciliAy"]
!= null)
return
ViewState["seciliAy"].ToString();
else
return "";
}
set {
ViewState["seciliAy"] = value;
}
}
public string SeciliYil
{
get
{
if (ViewState["seciliYil"]
!= null)
return
ViewState["seciliYil"].ToString();
else
return "";
}
set {
ViewState["seciliYil"] = value;
}
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<span id=’lblGun’>" +
GunMetin
+ "</span>");
writer.Write(" ");
writer.Write("<select name=’Gun’
id=’Gun’>");
for (int i = 1; i <= 31; i++)
{
if (SeciliGun==i.ToString())
writer.Write("<option selected=’selected’ value=’" +
i.ToString() + "’>" + i.ToString() + "</option>");
else
writer.Write("<option value=’" + i.ToString() + "’>" +
i.ToString() + "</option>");
}
writer.Write("</select>");
writer.Write(" ");
writer.Write("<span id=’lblAy’>" +
AyMetin
+ "</span>");
writer.Write(" ");
writer.Write("<select name=’Ay’
id=’Ay’>");
for (int i = 1; i <= 12; i++)
{
if (SeciliAy
== i.ToString())
writer.Write("<option selected=’selected’ value=’" +
i.ToString() + "’>" + i.ToString() + "</option>");
else
writer.Write("<option value=’" + i.ToString() + "’>" +
i.ToString() + "</option>");
}
writer.Write("</select>");
writer.Write(" ");
writer.Write("<span id=’lblYil’>" +
YilMetin
+ "</span>");
writer.Write(" ");
writer.Write("<select name=’Yil’
id=’Yil’>");
for (int i = 1950; i <= 2050; i++)
{
if (SeciliYil==i.ToString())
writer.Write("<option selected=’selected’ value=’" +
i.ToString() + "’>" + i.ToString() + "</option>");
else
writer.Write("<option value=’" + i.ToString() + "’>" +
i.ToString() + "</option>");
}
writer.Write("</select>");
base.Render(writer);
}
} |
Özelliklerimiz hepsi aynı prensiple
çalışmaktadır. Get bloklarında, eğer ViewState içerisinde tutulan bir
veri var ise bu veri string tipine dönüştürülerek elde edilir. Set bloğunda ise özelliğe atanan
değerler, ViewState içerisine bazı anahtar ifadeler (key) ile eklenmektedir.
Örneğin SeciliGun özelliğinin işaret edeceği değer için ViewState
içerisinde seciliGun isimli bir anahtara (key), değer ataması
yapılmıştır. Set blokları, dikkat ederseniz sayfanın Load olay metodu
içerisindeki kodlarda devreye girmektedir. Bu nedenle sayfa ilk üretilişi sırasında bu özelliklere
başlangıç değerleri atanmaktadır. Bu atama sonrasındaki değerler,
istemciye gönderilecek olan içerikte yer alan ViewState alanı içerisine
dahil edilecektir. Dolayısıyla istemci sayfayı tekrardan sunucuya
gönderdiğinde, açılan (yada deserialization işlemine tabi tutulan)
ViewState içerisinden, özelliklerin değerleri alınacaktır. Bu
değerleride Render metodu içerisinde özelliklerin Get bloklarından
aldığımızdan, kontrolün ilgili özellikleri başlangıç değerlerine
döndürülmeyecektir. Aşağıdaki video görüntüsünde kontrolümüzün yeni ve
eski halleri incelenmeye çalışılmıştır.
Üst taraftaki kontrolümüzü ViewState
kullanmayan TarihKontrolumOld isimli sınıfa ait bir örnektir. Alttaki
kontrolümüz ise TarihKontrolum sınıfına ait ViewState kullanan nesne
örneğimizdir. Halen daha bazı problemlerimiz vardır. Örneğin kullanıcı
tarayıcı penceresi içerisindeyken, gün, ay veya yıl bilgilerinden
birisini değiştirip sayfayı tekrardan sunucuya gönderirse, değiştirdiği
içeriği son hali ile elde edemeyecektir. Bu sayfanın içerisindeki
kontrollerin verisinin istemciden yapılan değişiklikler sonucu, sunucuya
gönderilmeyişinden kaynaklanmaktadır. Sorunu çözmek için postback işlemi sonucu istemciden gelen veriyi işlememiz gerekmektedir. Bu
sorunu nasıl çözeceğimizi yazı
dizimizin ilerleyen makalelerinde incelemeye çalıçacağız.
Makalemizin bundan sonraki bölümünde,
sunucu kontrollerimizin tasarım zamanındaki (design time) niteliklerini
(attribute) nasıl
değiştirebileceğimizi görmeye çalışacağız. Nitelikleri (attribute) sınıf(class), özellik(property)
veya assemblye bazında uygulayabiliriz. Bu nitelikler,
geliştirdiğimiz web sunucu kontrollerini kullanan sayfa geliştiriciler
için önemlidir. Nitekim, web sunucu kontrolünün Visual Studio.Net ortamı
içerisindeki davranışlarını belirlemektedir.
 |
Attribute’ lar
uygulandıkları tip veya üyelerin çalışma zamanındaki
davranışlarını belirlememize yarayan tiplerdir. Assembly’ ların Metadata’
sına eklendikleri için çalışma zamanıda reflection yardımıyla ele
alınırlar ve çalışma ortamının gerekli davranış değişikliklerini
yapabilmelerini sağlarlar. Çok
bilinen attribute’ lara örnek olarak Serialization, WebMethod,
WebService vb’ lerini verebiliriz. |
Geliştireceğimiz web sunucu kontrollerinde
kullanabileceğimiz sınıf(class), özellik(property) ve assembly
seviyesindeki bazı nitelikler(attributes) ve işlevleri aşağıdaki tabloda
özetlenmeye çalışılmıştır.
|
Assembly Bazındaki
Nitelikler (Attributes) |
Açıklaması |
|
TagPrefix |
Kontrol sayfaya sürüklenip
bırakıldığında, arka taraftaki elemente ait ön ekin (prefix)
ne olacacağını belirleyebilmemizi sağlar. |
|
Sınıf Bazındaki
Nitelikler (Attributes) |
Açıklaması |
|
ToolBoxData |
Bu nitelik ile kontrolün, sayfanın
arka tarafında nasıl yazılacağını belirtebiliriz. |
|
DefaultProperty |
Kontrol sayfaya ilk
sürüklendiğinde ele alınacak olan varsayılan özelliğin
(default property) ne
olacağını belirtir. Örneğin bir Button bileşeni için Text
özelliği varsayılandır. |
|
DefaultEvent |
Kontrol sayfaya ilk
sürüklendiğinde ele alınacak olan varsayılan olayın (default
event) ne olacağını
belirtir. Örneğin bir Button bileşeni için Click olayı
varsayılandır. |
|
Özellik Bazındaki
Nitelikler (Attributes) |
Açıklaması |
|
Browsable |
Bu nitelik ile, özelliğin Vs.Net
içerisindeki Properties penceresinde gösterilip gösterilmeyeceği
belirlenir. Varsayılan olarak özelliğin değeri true’ dur.
Üstelik kontroller içerisinde kullanılan her özellik bu niteliğe
varsayılan olarak sahiptir. |
|
Description |
Özellik ile ilgili bir açıklama
girilmesini sağlar. Bu, özellikle sayfa geliştiriciler (page
developers) için önemlidir.
Çünkü özelliğin ne amaçla kullanılacağı hakkında bilgilerin
verilmesini sağlamaktadır. |
|
Bindable |
Eğer özellik, veriye bağlanacaksa
(data binding) bu niteliğin kullanılması gerekir. |
|
Themeable |
Özelliğe theme ve dolayısıyla
skin
uygulanabilmesini sağlamak istiyorsak bu özelliği kullanırız. |
|
Category |
Özelliğin hangi kategori
(Category) başlığı
altında sunacağımızı belirtir. |
|
DefaultValue |
Özelliğin varsayılan olarak hangi
değeri (default value) taşıyacağını belirtmektedir. |
|
Localizable |
Eğer bu nitelik false olarak
belirtilirse, özelliğin içeriği söz konusu aspx için üretilen
resource sayfalarında gösterilmez. True olması halinde ise
gösterilir. Buda ilgili özelliğin yerelleştirmede
kullanılabilmesini sağlar. |
|
DesignOnly |
Özelliğin sadece tasarım zamanında
ele alınıp alınmayacağını belirtir. |
Dilerseniz bu nitelikleri ve etkilerini
incelemeye çalışalım. İlk olarak assembly seviyesindeki TagPrefix
niteliğini ele alacağız. Bu niteliği, kontrollerimizi barındıran
kütüphane içerisindeki AssemblyInfo.cs dosyası içerisinde
kullanmamız gerekmektedir. TagPrefix niteliği System.Web.UI
içerisinde yer aldığından, gerekli isim alanınında (namespace) bu sınıf
içerisine dahil etmekte fayda vardır. Temel olarak TagPrefix niteliği,
kontrolün web sayfası üzerine sürüklenmesi sonrasında arka planda
oluşturulacak olan elementin ön ekini belirlemek amacıyla kullanılır.
Varsayılan olarak cc1 olan kontrol elementi ön ekini değiştirmemizi
sağlayacaktır.
Dikkat ederseniz TagPrefix niteliğine ait
yapıcı metod (constructor) iki parametre almaktadır. Bu parametrelerden
ilki, kontrolün bulunduğu isim alanının adıdır. İkinci parametre ise ön
ekin adıdır. Bu değişiklilerden sonra kontrolümüzü herhangibir sayfa
üzerine sürükleyip bıraktığımızda aşağıdaki sonucu elde ederiz.
Gördüğünüz gibi kontrolümüzün ön eki,
assembly dosyasında belirttiğimiz şekilde değiştirilmiştir. Gelelim
diğer niteliklere. Sınıf bazında (Class Level) uygulayabileceğimiz
nitelikler için aşağıda bir örnek yer almaktadır.
[DefaultProperty("SeciliGun")]
[ToolboxData("<{0}:TarihKontrolum
runat=’Server’><{0}:TarihKontrolum>")]
public class TarihKontrolum:Control
{ |
Burada örnek olarak ToolboxData ve
DefaultProperty nitelikleri kullanılmıştır. ToolboxData, yazım
biçimindende görüldüğü gibi, kontrolün aspx tarafında nasıl yazılacağını
belirtmektedir. Tahmin edeceğiniz gibi {0} yazan yere,
AssemblyInfo.cs dosyasında tanımlanan TagPrefix niteliğindeki değer
gelecektir. İstenirse runat=’Server’ yazıldığı yerde başka attribute’
lar konularak, örneğin kontrolün özelliklerinin ilk değerlerinin
gösterilmesi sağlanabilir. Aşağıdaki kod parçasında bu durum
gösterilmiştir.
|
[ToolboxData("<{0}:TarihKontrolum
SeciliGun=’10’
SeciliAy=’2’
SeciliYil=’2007’
runat=’Server’><{0}:TarihKontrolum>")] |
Burada tanımlanan SeciliGun, SeciliAy ve
SeciliYil niteliklerinin aslında, TarihKontrolum sınıfı içerisindeki
özelliklere (properties) işaret ettiğine dikkat edelim. Yaptığımız değer
atamaları sonucu kontrolün bu özelliklerinin ilk değerleride otomatik
olarak set edilmiş olacaktır.
Kontrolün arka plandaki çıktısı ise
aşağıdaki gibi olacaktır.
<Kontrolum:TarihKontrolum ID="TarihKontrolum1" runat="server"
SeciliAy="2"
SeciliGun="10"
SeciliYil="2007">
</Kontrolum:TarihKontrolum> |
Sınıf bazında kullandığımız niteliklerden
DefaultProperty, kontrol sayfaya sürüklenip bırakıldığında, Vs.Net 2005
IDE’ si içerisindeki özellikler penceresinde, hangi özelliğin varsayılan
olarak seçili olacağını belirtmektedir. Örneğimizdeki TarihKontrolum
bileşeni için varsayılan özellik SeciliGun’ dür.
Gelelim özellik bazında kullandığımız
niteliklere. Kontrolümüzdeki özelliklerin hepsine yukarıda bahsettiğimiz
nitelikleri uygulayabiliriz. Örneğin SeciliGun için aşağıdaki örnek kod
parçasında tasarım penceresine etki edecek nitelikler eklenmiştir.
[Browsable(true)]
[Description("Hangi Gün?")]
[Bindable(true)]
[Themeable(true)]
[Category("Tarih Degerleri")]
[DefaultValue("1")]
[Localizable(true)]
public string SeciliGun
{
get
{
if (ViewState["seciliGun"] != null)
return
ViewState["seciliGun"].ToString();
else
return "";
}
set { ViewState["seciliGun"] = value; }
} |
Temel olarak Browsable niteliğini
yazmak şart değildir. Nitekim özelliklerin hepsi, tasarım zamanında
özellik penceresinde görünürler. Ancak bazı özelliklerin burada
değiştirilmesini istemediğimiz vakkalar olursa, false olarak
işaretlenebilir. DefaultValue özelliğine her ne kadar başlangıç
için 1 değerini atamış olsakta, ToolboxData niteliği içerisinde
bu özellik için yeni bir değer verilmiştir. Bunun doğal sonucu olarak,
DefaultValue özelliğindeki değer yerine ToolboxData içerisindeki özellik
değeri, özellikler penceresinde görünecektir. Themeable niteliği,
Asp.Net 2.0 ile birlikte gelmiş olan tema kavramına istinaden
kullanılabilir. Eğer false değeri atanırsa özelliğimize tema veya skin
uygulanamayacaktır. Localizable özelliğine true değerinin
atanması ile, SeciliGun değerinin resource dosyalarında görünmesi
sağlanır. Örneğin tüm özelliklerimizde bu niteliği true olarak
kullandığımızda aşağıdaki gibi bir resource dosyası üretilebilir.
Categroy niteliğini kullandığımız
takdirde, özelliklerin properties bölümünde mantıksal isim başlıkları
altında yer alması sağlanabilir. Örneğin SeciliGun,SeciliAy, SeciliYil
özelliklerini Tarih Degerleri isimli bir grup altında toplayabiliriz.
Benzer bir şekilde, AyMetin, GunMetin ve YilMetin özelliklerini Metinler
adında bir grup başlığında toplayabiliriz. Sonuç aşağıdakine benzer
olacaktır.
Gördüğünüz gibi, geliştireceğimiz
kontrollerin tasarım zamanındaki davranışlarını niteliklerimiz
yardımıyla belirleyebilmekteyiz. Bu makalemizde web kontrolü
geliştirmekle ilgili olarak, state yönetimini ViewState’ ler yardımıyla
nasıl yapabileceğimizi, tasarım zamanındaki davranışları nasıl
belirleyebileceğimizi incelemeye çalıştık. Şu ana kadar yaptıklarımız
ile ilgili olarak aklımızda kalanları ise aşağıdaki maddeler ile
özetleyebiliriz.
| Şu Ana
Kadar Hatırda Kalanlar |
| Bir web
sunucu kontrolünün sayfanın yüklenişi sırasında set edilen
değerlerini korumak için özelliklerin içerisindeki verileri
ViewState’ ler içerisinde saklamak gerekir. |
| ViewState
kullanmak, kontrolün istemci tarafında değişikliğe uğrayacak
değerlerini ele almak için yeterli değildir. Bu durumda işin
içerisinde postback sonucu sunucuya gönderilecek dataların ele
alınması gibi şartlar girmektedir. |
| Web sunucu
kontrollerine tasarım zamanı desteği sağlanabilir. Böylece
Vs.Net IDE’ si içerisindeki davranış modelleri ele alınabilir. |
| Tasarım
zamanı davranışlarını belirleyen nitelikleri Assembly, Class ve
Property olmak üzere toplam üç seviyede belirleyebiliriz. |
Böylece geldik bir makalemizin daha
sonuna. Sonraki makalemizde Render metodu ile ilişkili başka düzenlemer
yapacak ve PostBack olaylarını nasıl ele alabileceğimizi araştırmaya
çalışacağız. Bir sonraki makalemizde görüşmek dileğiyle hepinize mutlu günler
dilerim.Burak Selim ŞENYURT
selim@bsenyurt.com
Makale:
Web Server Control Yazmak - 2 ASP.NET Burak Selim Şenyurt
|
|
Bu konu hakkında yayınlanan yorum bulunmamaktadır.
"Yorum Yaz" tabını kullanarak sizde yorumlarınızı yazabilirsiniz.
|
|
|
|
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|
|
|