ASP.NET 4.0'da ClientIDMode ile HTML ID'lerinin kontrolü.

0 dakikada yazıldı

12634 defa okundu

Düzenle

ASP.NET'te en sevmediğim özelliklerden biri yaratılan HTML kodu
üzerindeki kontrolün pek de mümkün olmaması. Aslında bu sevmediğim
özellik ASP.NET'in işimizi bu kadar kolaylaştırabilmesini sağlayan en
önemli altyapısı ile ilişkili. Fakat derdime çare arayacak olsam aslında
tam olarak da yaratılan HTML kontrollerinin ID'lerine takıldığımı
söyleyebilirim. Boyumu aşan ID'leri kontrol edememek bir de bu ID'lere
JavaScript ile ulaşmak zorunda kalmak ölümcül bir deneyim!

Neden bahsediyorsun?

Bahsettiğim şey aslında basit bir Repeater bile olabilir. Örneğin
sayfanıza bir Repeater yerleştirdiniz ve içinde de çok basit bir Label
bulunuyor. Aslında tek yapmak istediğiniz elinizdeki ürünlerin
isimlerini listelemek diyelim. Bu durumda kabaca kullanacağınız Repeater
yapısı aşağıdaki gibi olacaktır.

[ASP.NET]

<asp:repeater id="Repeater1" runat="server">

    <ItemTemplate>

        <asp:Label
ID="lbl_UrunAdi" runat="server" Text='<%# Eval("Adi") %>'></asp:Label>

    </ItemTemplate>

</asp:repeater>

Peki bu ASP.NET kodu çalıştığında ortaya HTML olarak ne çıkacak
dersiniz? Gelin aşağıdaki HTML'i beraber inceleyelim.

 [HTML]

<span id="Repeater1_ctl00_lbl_UrunAdi">Örnek1</span>

<span id="Repeater1_ctl01_lbl_UrunAdi">Örnek2</span>

<span id="Repeater1_ctl02_lbl_UrunAdi">Örnek3</span>

<span id="Repeater1_ctl03_lbl_UrunAdi">Örnek4</span>

<span id="Repeater1_ctl04_lbl_UrunAdi">Örnek5</span>

<span id="Repeater1_ctl05_lbl_UrunAdi">Örnek6</span>

<span id="Repeater1_ctl06_lbl_UrunAdi">Örnek7</span>

<span id="Repeater1_ctl07_lbl_UrunAdi">Örnek8</span>

<span id="Repeater1_ctl08_lbl_UrunAdi">Örnek9</span>

<span id="Repeater1_ctl09_lbl_UrunAdi">Örnek10</span>

Yukarıdaki kodda da gördüğünüz üzere her bir Label / Span tagının ayrı
bir ID'si var. Zaten olması gereken de bu, çünkü bir sayfada ancak aynı
ID'den bir adet bulunabilir. Fakat ASP.NET'in bu farklı ID'leri
yaratırken izlediği yol biraz farklı. İlk olarak container elementin adı
alınıyor sonra ctl ile başlayan satır Index numarası kullanılıyor sonra
da içerideki orijinal kontrolün adı ekleniyor ve ortaya kocaman bir ID
çıkıyor. Bu ID'lerin her birini üç karakterlik isimlere kısaltmış olsak
ciddi miktarda web sitesi trafiğini de azaltmış olacağız. Hadi trafiği
geçtik bu Label'lardan birine JavaScript ile ulaşmak isterseniz ne
yapacaksınız? Eminim çoğunuzun dinamik JavaScript kodları yarattığı ve
içlerine sunucu tarafından istedikleri kontrollerin ClientID'lerini
koydukları günler vardı. Geçmiş zamanla konuşuyorum çünkü ASP.NET 4.0
ile bu sistem değişiyor.

Hoş geldin ClientIDMode!
Hoş geldin ClientIDMode!

Artık kontrol başına ClientIDMode belirleyerek söz konusu kontrolün
istemci taraflı ID'sinin ne şekilde yaratılacağını kontrol edebiliyoruz.
Peki ClientIDMode için gelen seçenekler nelerdir?

AutoID: Herşey eskisi gibi devam eder.
Inherit: Bir üst kontrolde bu özellik nasıl ayarlanmış ise aynısı
alt kontrolde de geçerli olur.
Predictable: Eski ID'lere benzeye fakat şekli şemali kontrol
edilebilir ID yapıları oluşturulmasını sağlar. Bu yapı daha fazla
DataBound kontrollerin içi için kullanılır.
Static: Söz konusu kontrolün sunucu tarafındaki ID'si ne ise istemci
tarafındaki da bire bir aynı olur. Bu noktada bir sayfa içerisinde aynı
ID'nin tekrar kullanılmaması sizin sorumluluğunuzdadır. Özellikle
Repeater gibi yapıların içinde kullanımı tehlikeli olabilir.

Static

Eğer herhangi bir kontrolün ClientIDMode'unu Static olarak ayarlarsanız
sunucu tarafındaki ID doğrudan istemciye gönderilecektir. Örneğin bir
üstteki Repeater içerisindeki Label'ın ClientIDMode özelliğini Static
yaparsak alacağımız sonuç aşağıdaki gibi olur.

[HTML]

 <span id="lbl_UrunAdi">Örnek1</span>

<span id="lbl_UrunAdi">Örnek2</span>

<span id="lbl_UrunAdi">Örnek3</span>

<span id="lbl_UrunAdi">Örnek4</span>

<span id="lbl_UrunAdi">Örnek5</span>

<span id="lbl_UrunAdi">Örnek6</span>

<span id="lbl_UrunAdi">Örnek7</span>

<span id="lbl_UrunAdi">Örnek8</span>

<span id="lbl_UrunAdi">Örnek9</span>

<span id="lbl_UrunAdi">Örnek10</span>

Gördüğünüz gibi tüm Span tagları aynı ID özelliğine sahip. Bu durum tabi
ki tehlikeli çünkü bu durumda bir JavaScript ile bu kontrollerin
hiçbirini bulamayız. Zaten durum kurallara aykırı fakat yaptığımız hata
basit. Static modu kesinlikle DataBound kontrollerin içerisindeki
kontrollerde kullanılmamalı. DataBound kontroller hariç sayfada tekil
kullandığınız kontroller için rahatlıkla Static modunu
kullanabilirsiniz.

Predictable

Databound kontrollerin içi için kullanılabilecek en anlamlı çözüm
Predictable modudur. Bu modda varsayılan ayarları ile ilk önce container
elementin ismi alınır sonra iç elementin ismi alınır ve en sona da Index
numarası yerleştirilir. Yine en üstteki Repeater örneğimizi ele alalım
ve Repeater'ın ClientIDMode özelliğini aşağıdaki gibi
Predictable şeklinde düzenleyelim.

[ASP.NET]

<asp:Repeater ID="Repeater1" runat="server"
ClientIDMode
="Predictable">

    <ItemTemplate>

        <asp:Label
ID="lbl_UrunAdi" runat="server" Text='<%# Eval("Adi") %>'></asp:Label>

    </ItemTemplate>

</asp:Repeater>

Kodumuzu çalıştırdığımız aldığımız HTML sonucu aşağıdaki şekilde
olacaktır.

 <span id="Repeater1_lbl_UrunAdi_0">Örnek1</span>

<span id="Repeater1_lbl_UrunAdi_1">Örnek2</span>

<span id="Repeater1_lbl_UrunAdi_2">Örnek3</span>

<span id="Repeater1_lbl_UrunAdi_3">Örnek4</span>

Gördüğünüz gibi en azından bildiğim isimler kullanılmış ve ana
repeater'in isminin yanına label'ın ismi sonra da Index numarası
yerleştirilmiş. Bu noktada maalesef Repeater ve Label'a verdiğimiz
isimlerin uzunlukları da önem kazanıyor.

Predictable modunda kullanabileceğiniz bir diğer özellik ise
ClientIDRowSuffix özelliği. Fakat maalesef bu özelliği sadece
DataKey koleysiyonları tutan kontrollerde kullanabilirsiniz. Örneğin bir
GridView bunun için uygun olacaktır.

[ASP.NET]

<asp:gridview id="BirGrid" runat="server" autogeneratecolumns="false"
clientidmode
="Predictable"

**   ** clientidrowsuffix="ID">

    <Columns>

        <asp:TemplateField HeaderText="ID">

            <ItemTemplate>

                <asp:Label
ID="lbl_Adi" runat="server" Text='<%# Eval("Adi") %>' />

            </ItemTemplate>

        </asp:TemplateField>

    </Columns>

</asp:gridview>

Yukarıda gördüğünüz GridView'ın ClientIDRowSuffix özelliğine ID
değeri verilmiş. Böylece yaratılan ID'lerin sonunda artık Index numarası
değil doğrudan veritabanından gelen ID değeri yerleştirilecek.

[HTML]

<table cellspacing="0" rules="all"
border="1" id="BirGrid" style="border-collapse: collapse;">

    <tr>

        <th scope="col">

            ID

        </th>

    </tr>

    <tr>

        <td>

            <span id="BirGrid_lbl_Adi_3">Örnek1</span>

        </td>

    </tr>

    <tr>

        <td>

            <span id="BirGrid_lbl_Adi_4">Örnek2</span>

        </td>

    </tr>

    <tr>

        <td>

            <span id="BirGrid_lbl_Adi_5">Örnek3</span>

        </td>

    </tr>

    <tr>

        <td>

            <span id="BirGrid_lbl_Adi_6">Örnek4</span>

        </td>

    </tr>

Hemen kodumuzdaki Label'ların ID'lerine bakarsak Grid'in adını, sonra
Label'ın adını ve en sonunda da ID değerlerini görebiliyoruz. Malum ID
değerlerin kayıtların sırası ile aynı olmayabilirler. Bu gibi bir teknik
ile kontrollerin ID'leri set edildiğinde JavaScript ile veritabanından
gelen değerlere göre sayfada uygun kontrolleri bulmak da çok daha
kolaylaşıyor.

Başka nasıl ayarlanır?

Eğer isterseniz ClientIDMode özelliğini projelerinde sayfa bazında
veya uygulama bazında da ayarlayabilirsiniz.

<%@ Page
Language="VB" AutoEventWireup="false"
ClientIDMode
="Static"
CodeFile="Default.aspx.vb" Inherits="_Default" %>

Yukarıdaki şekli ile bir sayfada ClientIDMode ayarlamak tüm sayfa için
geçerli olmasını sağlayacaktır. Ayrıca uygulama bazında da Web.Config
içerisinde gerekli ayarı yapabilirsiniz.

<system.web>

    <pages clientIdMode="Predictable"></pages>

</system.web>

Hepinize kolay gelsin.