Skip to content

8. ASP sunucu bileşenleri - 2

8.1. Introduction

Kullanıcı arayüzü üzerindeki çalışmalarımıza devam ederek şunları inceliyoruz:

  • veri doğrulama bileşenleri
  • verileri sunucu bileşenlerine bağlama yöntemi
  • HTML sunucu bileşenleri

8.2. Veri doğrulama bileşenleri

8.2.1. Giriş

Form tabanlı uygulamalarda, formlara girilen verilerin geçerliliğini kontrol etmek son derece önemlidir. Vergi hesaplama örneğinde, aşağıdaki form vardı:

Image

Bu formdan gelen değerleri aldığımızda, girilen verilerin geçerliliğini kontrol etmemiz gerekir: çocuk sayısı ve maaş, pozitif tamsayılar veya sıfır olmalıdır. Aksi takdirde, form, hataları belirten mesajlarla birlikte girildiği haliyle müşteriye geri gönderilir. Bu durumu iki görünümle ele almıştık; biri yukarıdaki form için, diğeri ise hatalar içindi:

Image

ASP.NET, aşağıdaki durumları doğrulamaya olanak tanıyan "doğrulama bileşenleri" adı verilen bileşenler sunar:

Bileşen
Rol
RequiredFieldValidator
bir alanın boş olup olmadığını doğrular
CompareValidator
iki değeri birbiriyle karşılaştırır
RangeValidator
bir değerin iki sınır arasında olup olmadığını kontrol eder
RegularExpressionValidator
bir alanın düzenli ifadeyi karşılayıp karşılamadığını kontrol eder
CustomValidator
geliştiricinin kendi doğrulama kurallarını belirlemesine olanak tanır - bu bileşen diğer tüm bileşenlerin yerini alabilir
ValidationSummary
önceki denetimler tarafından üretilen hata mesajlarını sayfanın tek bir yerinde toplar

Şimdi bu bileşenlerin her birini tek tek tanıtacağız.

8.2.2. RequiredFieldValidator

Aşağıdaki [requiredfieldvalidator1.aspx] sayfasını oluşturuyoruz:

no
ad
tür
özellikler
rol
1
txtNom
TextBox
EnableViewState=true
giriş alanı
2
RequiredFieldValidator1
RequiredFieldValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=[ad] alanı zorunludur
doğrulama bileşeni
3
btnEnvoyer
Düğme
EnableViewState=false
Doğrulama Nedenleri=true
[submit] düğmesi

[RequiredFieldValidator1] alanı, [txtNom] alanı boşsa veya bir dizi boşluk içeriyorsa bir hata mesajı görüntülemek için kullanılır. Özellikleri şunlardır:

ControlToValidate
değeri bileşen tarafından kontrol edilmesi gereken alan. Bir bileşenin değeri ne anlama gelir? Bu, ilgili HTML etiketinin [value] özniteliğinin değeridir. [TextBox] için bu, giriş alanının içeriği; [DropDownList] için ise seçilen öğenin değeri olacaktır.
EnableClientScript
boole - "true" değeri, önceki alanın içeriğinin istemci tarafında da kontrol edilmesi gerektiğini belirtir. Bu durumda, formda hata bulunmadığı takdirde form tarayıcı tarafından gönderilir. Bununla birlikte, örneğin istemcinin bir tarayıcı olmaması durumuna karşı, doğrulama testleri sunucu tarafında da yapılır.
ErrorMessage
Hata tespit edildiğinde bileşenin görüntülemesi gereken hata mesajı

Doğrulama denetimleri aracılığıyla sayfadaki verilerin kontrolü, yalnızca sayfadaki [POST]'i tetikleyen düğme veya bağlantının [CausesValidation=true] özelliğine sahip olması durumunda yapılır. [true], bu özelliğin varsayılan değeridir.

Bu uygulamayı çalıştıralım. Öncelikle bir [Mozilla] tarayıcısı kullanıyoruz:

Image

[Mozilla] tarafından alınan HTML kodu şöyledir:

<html>
<head>
</head>
<body>
    <form name="_ctl0" method="post" action="requiredfieldvalidator1.aspx" id="_ctl0">
<input type="hidden" name="__VIEWSTATE" value="dDwxNDI1MDc1NTU1Ozs+SGtdZvVxefDCDxnsqbDnqCaROsk=" />

        <p>
            Demande du dossier de candidature au DESS 
        </p>
        <fieldset>
            <legend>[--Identité--]</legend>

            <table>
                <tbody>
                    <tr>
                        <td>
                            Nom*</td>
                        <td>
                            <input name="txtNom" type="text" id="txtNom" />
                            &nbsp;
                        </td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
        <p>
            <input type="submit" name="btnEnvoyer" value="Envoyer" onclick="if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate(); " language="javascript" id="btnEnvoyer" />
        </p>
    </form>

</body>
</html>

[btnEnvoyer] düğmesinin, [onclick] özniteliği aracılığıyla bir JavaScript işlevine bağlı olduğu görülmektedir. Ayrıca, sayfada [Javascript] kodunun bulunmadığı da fark edilebilir. [typeof(Page_ClientValidate) == 'function'] testi başarısız olacak ve JavaScript işlevi çağrılmayacaktır. Form daha sonra sunucuya gönderilecek ve geçerlilik kontrolleri sunucu tarafından yapılacaktır. [Envoyer] düğmesini isim girmeden kullanalım. Sunucudan gelen yanıt şöyledir:

Image

Ne oldu? Form sunucuya gönderildi. Sunucu, sayfada bulunan tüm doğrulama bileşenlerinin kodunu çalıştırdı. Burada sadece bir tane var. En az bir doğrulama bileşeni bir hata tespit ederse, sunucu formu girildiği haliyle geri gönderir (aslında [EnableViewState=true] özniteliğine sahip bileşenler için, ayrıca hata tespit eden her doğrulama bileşeni için bir hata mesajı da ekler). Bu mesaj, doğrulama bileşeninin [ErrorMessage] özniteliğidir. Yukarıda iş başında gördüğümüz mekanizma budur. [nom] alanına bir şey girersek, formu gönderdiğimizde hata mesajı artık görünmez:

Image

Şimdi Internet Explorer'ı kullanarak [http://localhost/requiredfieldvalidator1.aspx] URL'sini çağıralım. Aşağıdaki sayfayı görürüz:

Image

IE tarafından alınan HTML kodu şöyledir:

<html>
<head>
</head>
<body>
    <form name="_ctl0" method="post" action="requiredfieldvalidator1.aspx" language="javascript" onsubmit="ValidatorOnSubmit();" id="_ctl0">
<input type="hidden" name="__VIEWSTATE" value="dDwxNDI1MDc1NTU1Ozs+SGtdZvVxefDCDxnsqbDnqCaROsk=" />

<script language="javascript" src="/aspnet_client/system_web/1_1_4322/WebUIValidation.js"></script>


        <p>
            Demande du dossier de candidature au DESS 
        </p>
        <fieldset>
            <legend>[--Identité--]</legend>
            <table>
                <tbody>
                    <tr>
                        <td>
                            Nom*</td>
                        <td>
                            <input name="txtNom" type="text" id="txtNom" />
                            <span id="RequiredFieldValidator1" controltovalidate="txtNom" errormessage="Le champ [nom] est obligatoire" evaluationfunction="RequiredFieldValidatorEvaluateIsValid" initialvalue="" style="color:Red;visibility:hidden;">Le champ [nom] est obligatoire</span>
                        </td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
        <p>
            <input type="submit" name="btnEnvoyer" value="Envoyer" onclick="if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate(); " language="javascript" id="btnEnvoyer" />
        </p>

<script language="javascript">
<!--
    var Page_Validators =  new Array(document.all["RequiredFieldValidator1"]);
        // -->
</script>


<script language="javascript">
<!--
var Page_ValidationActive = false;
if (typeof(clientInformation) != "undefined" && clientInformation.appName.indexOf("Explorer") != -1) {
    if (typeof(Page_ValidationVer) == "undefined")
        alert("Impossible de trouver la bibliothèque de scripts /aspnet_client/system_web/1_1_4322/WebUIValidation.js. Essayez de placer ce fichier manuellement ou effectuez une réinstallation en exécutant 'aspnet_regiis -c'.");
    else if (Page_ValidationVer != "125")
        alert("Cette page utilise une version incorrecte de WebUIValidation.js. La page requiert la version 125. La bibliothèque de scripts est " + Page_ValidationVer + ".");
    else
        ValidatorOnLoad();
}

function ValidatorOnSubmit() {
    if (Page_ValidationActive) {
        ValidatorCommonOnSubmit();
    }
}
// -->
</script>


        </form>
</body>
</html>

Bu kodun, [Mozilla] tarafından alınan koddan çok daha uzun olduğu görülüyor. Ayrıntılara girmeyeceğiz. Aradaki fark, sunucunun gönderilen HTML belgesine javascript işlevleri eklemesinden kaynaklanıyor. İki tarayıcı tarafından istenen URL aynı olmasına rağmen neden iki farklı HTML kodu var? Daha önce de belirttiğimiz gibi, ASP.NET teknolojisi, sunucunun müşteriye gönderdiği HTML belgesini o müşterinin gereksinimlerine göre uyarlamasını sağlıyordu. Piyasada, hepsi aynı yeteneklere sahip olmayan farklı tarayıcılar bulunmaktadır. Örneğin, Microsoft ve Netscape tarayıcıları, aldıkları belge için aynı nesne modellemesini kullanmazlar. Dolayısıyla, bu belgeyi tarayıcı tarafında işlemek için kullanılan JavaScript kodu, iki tarayıcı arasında farklılıklar gösterir. Benzer şekilde, yazılım geliştiriciler, tarayıcılarının yeteneklerini sürekli olarak geliştiren yeni sürümler oluşturmuşlardır. Bu nedenle, IE5 tarafından anlaşılan bir HTML belgesi, IE3 tarafından anlaşılamayabilir. Yukarıda, sunucunun istemci düzeyinde yaptığı bu uyarlamaya ilişkin bir örnek verilmiştir. Burada ayrıntılı olarak ele alınmayan bir nedenden ötürü, web sunucusu [Mozilla] istemcisinin doğrulama amaçlı JavaScript kodunu işleme kapasitesine sahip olmadığını değerlendirmiştir. Bu nedenle, bu kod kendisine gönderilen HTML belgesine eklenmemiş ve doğrulama işlemi sunucu tarafında gerçekleştirilmiştir. [IE6] için ise, gördüğümüz gibi bu JavaScript kodu gönderilen HTML belgesine dahil edilmiştir. Bunun nasıl çalıştığını görmek için şu deneyi yapalım:

  • web sunucusunu durduralım
  • [nom] alanını doldurmadan [Envoyer] düğmesini kullanalım

Şu yeni sayfayı elde ediyoruz:

Image

Hata mesajını görüntüleyen gerçekten de tarayıcıdır. Nitekim sunucu durdurulmuştur. [nom] alanına bir şey girip göndererek bunu doğrulayabiliriz. Bu sefer yanıt şöyledir:

Image

Ne oldu? Tarayıcı, doğrulama için JavaScript kodunu çalıştırdı. Bu kod, sayfanın geçerli olduğunu bildirdi. Bunun üzerine tarayıcı, formu kapalı olan web sunucusuna gönderdi. Tarayıcı bunu fark etti ve yukarıdaki sayfayı görüntüledi. Sunucuyu yeniden başlatırsak her şey normale döner.

Bu örnekten ne öğrenebiliriz?

  • Yanlış doldurulmuş formları müşteriye geri göndermek için kullanılan "doğrulama bileşeni" kavramının önemi
  • [VIEWSTATE]'in önemi; bu kod, formun girildiği haliyle geri gönderilmesini sağlar
  • Sunucunun müşteriye uyum sağlama yeteneği. Müşteri, sunucuya gönderdiği HTTP [User-Agent:] başlığıyla tanımlanır. Dolayısıyla, kiminle karşı karşıya olduğunu "tahmin eden" sunucu değildir. Bu uyum yeteneği, uygulamasının istemci türünü dert etmesine gerek kalmayan geliştirici için büyük önem taşır.

8.2.3. CompareValidator

Aşağıdaki [comparevalidator1.aspx] sayfasını oluşturuyoruz:

Image

no
ad
tür
özellikler
rol
1
cmbChoix1
DropDownList
EnableViewState=true
açılır liste
2
cmbChoix2
DropDownList
EnableViewState=true
açılır liste
3
CompareValidator1
CompareValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=Seçim 1 geçersiz
KarşılaştırılacakDeğer=?
Operatör=Eşit Değil
Tür=dize
doğrulama bileşeni
4
CompareValidator2
CompareValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=Seçim 2 geçersiz
Karşılaştırılacak Kontrol=?
Operatör=Eşit Değil
Type=string
doğrulama bileşeni
5
btnEnvoyer
Düğme
EnableViewState=false
Doğrulama Nedenleri=true
[submit] düğmesi

[CompareValidator] bileşeni, iki değeri birbiriyle karşılaştırmak için kullanılır. Kullanılabilen operatörler [Equal, NotEqual, LessThan, LessThanEqual, GreaterThan, GreaterThanEqual]'tir. İlk değer [ControlToValidate] özelliği ile belirlenir; ikinci değer ise önceki değer bir sabitle karşılaştırılacaksa [ValueToCompare], başka bir bileşenin değeriyle karşılaştırılacaksa [ControlToCompare] ile belirlenir. [CompareValidator] bileşeninin önemli özellikleri şunlardır:

ControlToValidate
içeriği bileşen tarafından kontrol edilmesi gereken alan
EnableClientScript
boole değeri - "true" ise, önceki alanın içeriğinin istemci tarafında da kontrol edilmesi gerektiğini belirtir
ErrorMessage
hata tespit edildiğinde bileşenin görüntülemesi gereken hata mesajı
ValeurToCompare
[ControlToValidate] alanının değeriyle karşılaştırılması gereken değer
ControlToCompare
[ControlToValidate] alanının değeriyle karşılaştırılması gereken bileşen
Operator
iki değer arasındaki karşılaştırma operatörü
Type
karşılaştırılacak değerlerin türü

Bu sayfanın sunum kodu şöyledir:

<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Demande du dossier de candidature au DESS 
        </p>
        <fieldset>
            <legend>[--Options du DESS pour lesquelles vous candidatez--]</legend>
            <table>
                <tbody>
                    <tr>
                        <td>
                            Option1*</td>
                        <td>
                            Option2</td>
                    </tr>
                    <tr>
                        <td>
                            <asp:DropDownList id="cmbChoix1" runat="server">
                                <asp:ListItem Value="?" Selected="True">?</asp:ListItem>
                                <asp:ListItem Value="Automatique">Automatique</asp:ListItem>
                                <asp:ListItem Value="Informatique">Informatique</asp:ListItem>
                            </asp:DropDownList>
                        </td>
                        <td>
                            <asp:DropDownList id="cmbChoix2" runat="server">
                                <asp:ListItem Value="?">?</asp:ListItem>
                                <asp:ListItem Value="Automatique">Automatique</asp:ListItem>
                                <asp:ListItem Value="Informatique">Informatique</asp:ListItem>
                            </asp:DropDownList>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <asp:CompareValidator id="CompareValidator1" runat="server" ErrorMessage="Choix 1 invalide" ControlToValidate="cmbChoix1" ValueToCompare="?" Operator="NotEqual"></asp:CompareValidator>
                        </td>
                        <td>
                            <asp:CompareValidator id="CompareValidator2" runat="server" ErrorMessage="Choix 2 invalide" ControlToValidate="cmbChoix2" Operator="NotEqual" ControlToCompare="cmbChoix1"></asp:CompareValidator>
                        </td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
        <p>
            <asp:Button id="btnEnvoyer" runat="server" Text="Envoyer"></asp:Button>
        </p>
    </form>
</body>
</html>

Sayfanın doğrulama kısıtlamaları şunlardır:

  • [cmbChoix1]'te seçilen değer, "?" dizesinden farklı olmalıdır. Bu, [CompareValidator1] bileşeni için aşağıdaki özellikleri gerektirir: Operator=NotEqual, ValueToCompare=?, Type=string
  • [cmbChoix2]'te seçilen değer, [cmbChoix1]'te seçilen değerden farklı olmalıdır. Bu, [CompareValidator2] bileşeni için aşağıdaki özellikleri gerektirir: Operatör=NotEqual, ControlToCompare=cmbChoix1, Tür=dize

Bu uygulamayı çalıştırıyoruz. İşte istemci-sunucu iletişimi sırasında alınan bir sayfa örneği:

Image

Aynı sayfa Internet Explorer 6 ile çağrıldığında, sayfaya eklenen JavaScript kodu sayesinde işleyiş biraz farklılaşır. Kullanıcı açılır listelerden birinde değeri değiştirdiğinde olası hatalar hemen bildirilir. Bu, kullanıcı deneyimini iyileştiren bir özelliktir.

8.2.4. CustomValidator, RangeValidator

Aşağıdaki [customvalidator1.aspx] sayfasını oluşturuyoruz:

Image

no
ad
tür
özellikler
rol
1
cmbDiplomes
DropDownList
EnableViewState=true
açılır liste
2
CompareValidator2
CompareValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=Geçersiz diploma
Operatör=Eşit Değil
Karşılaştırılacak Değer=?
Type=String
[1] denetiminin doğrulama bileşeni
3
txtAutreDiplome
TextBox
EnableViewState=false
giriş alanı
4
CustomValidator1
CustomValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=Diploma doğruluğu geçersiz
ClientValidationFunction=chkAutreDiplome
alan doğrulama bileşeni [3]
5
txtAnDiplome
TextBox
EnableViewState=false
giriş alanı
6
RangeValidator1
RangeValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=Mezuniyet yılı [1990,2004] aralığında olmalıdır
MinValue=1990
MaxValue=2004
Type=Tamsayı
ControlToValidate=txtAnDiplome
[5] alanının doğrulama bileşeni
7
RequiredFieldValidator2
RequiredFieldValidator
EnableViewState=false
EnableClientScript=true
ErrorMessage=Mezuniyet yılı gereklidir
ControlToValidate=txtAnDiplome
alan doğrulama bileşeni [5]
8
btnEnvoyer
Düğme
EnableViewState=false
CausesValidation=true
[submit] düğmesi

[RangeValidator] alanı, bir denetim değerinin [MinValue] ve [MaxValue] sınırları arasında olup olmadığını doğrulamak için kullanılır. Özellikleri şunlardır:

ControlToValidate
değeri bileşen tarafından kontrol edilmesi gereken alan
EnableClientScript
boole değeri - "true" ise, önceki alanın içeriğinin istemci tarafında da kontrol edilmesi gerektiğini belirtir
ErrorMessage
hata tespit edildiğinde bileşenin görüntülemesi gereken hata mesajı
MinValue
denetlenecek alanın değerinin minimum değeri
MaxValue
denetlenecek alanın değerinin maksimum değeri
Type
denetlenecek alanın değer türü

[CustomValidator] alanı, ASP.NET tarafından sunulan doğrulama bileşenlerinin yapamadığı doğrulamaları yapmanıza olanak tanır. Bu doğrulama, geliştirici tarafından yazılan bir işlevle gerçekleştirilir. Bu işlev sunucu tarafında çalıştırılır. Doğrulama işlemine istemci tarafında da yapılabileceğinden, geliştirici HTML belgesine ekleyeceği bir JavaScript işlevi geliştirebilir. Bu işlevin özellikleri şunlardır:

ControlToValidate
değeri bileşen tarafından kontrol edilmesi gereken alan
EnableClientScript
boole değeri – "true" ise, önceki alanın içeriğinin istemci tarafında da kontrol edilmesi gerektiğini belirtir
ErrorMessage
hata tespit edildiğinde bileşenin görüntülemesi gereken hata mesajı
ClientValidationFunction
istemci tarafında çalıştırılacak işlev

Sayfanın görüntüleme kodu şöyledir:

<%@ Page Language="VB" %>
<script runat="server">
...
</script>
<html>
<head>
</head>
<body>
    <form runat="server">
        <p align="left">
            Demande du dossier de candidature au DESS 
        </p>
        <fieldset>
            <legend>[--Votre dernier diplôme--]</legend>
            <table>
                <tbody>
                    <tr>
                        <td>
                            Diplôme*</td>
                        <td>
                            <asp:DropDownList id="cmbDiplomes" runat="server">
                                <asp:ListItem Value="?">?</asp:ListItem>
                                <asp:ListItem Value="[Autre]">[Autre]</asp:ListItem>
                                <asp:ListItem Value="Ma&#238;trise">Ma&#238;trise</asp:ListItem>
                                <asp:ListItem Value="DESS">DESS</asp:ListItem>
                                <asp:ListItem Value="DEA">DEA</asp:ListItem>
                            </asp:DropDownList>
                        </td>
                        <td>
                            Si [Autre], précisez</td>
                        <td>
                            <asp:TextBox id="txtAutreDiplome" runat="server" EnableViewState="False"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td>
                        </td>
                        <td>
                            <p>
                                <asp:CompareValidator id="CompareValidator2" runat="server" ErrorMessage="Diplôme invalide" ControlToValidate="cmbDiplomes" ValueToCompare="?" Operator="NotEqual" ></asp:CompareValidator>
                            </p>
                        </td>
                        <td>
                        </td>
                        <td>
                            <asp:CustomValidator id="CustomValidator1" runat="server" ErrorMessage="Précision diplôme invalide" OnServerValidate="CustomValidator1_ServerValidate_1" EnableViewState="False" ClientValidationFunction="chckAutreDiplome"></asp:CustomValidator>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            Année d'obtention*</td>
                        <td colspan="3">
                            <asp:TextBox id="txtAnDiplome" runat="server" Columns="4"></asp:TextBox>
                            <asp:RangeValidator id="RangeValidator1" runat="server" ErrorMessage="Année diplôme doit être dans l'intervalle [1990,2004]" ControlToValidate="txtAnDiplome" MinimumValue="1990" MaximumValue="2004" Type="Integer"></asp:RangeValidator>
                            <asp:RequiredFieldValidator id="RequiredFieldValidator2" runat="server" ErrorMessage="Année diplôme requise" ControlToValidate="txtAnDiplome"></asp:RequiredFieldValidator>
                        </td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
        <p>
            <asp:Button id="btnEnvoyer" runat="server" Text="Envoyer"></asp:Button>
        </p>
    </form>
</body>
</html>

[CustomValidator] bileşeninin [OnServerValidate] özniteliği, sunucu tarafında doğrulama işleminden sorumlu işlevi belirtmeye yarar. Yukarıda, [CustomValidator1] bileşeni aşağıdaki [CustomValidator1_ServerValidate_1] yordamını çağırmaktadır:

<%@ Page Language="VB" %>
<script runat="server">

    Sub CustomValidator1_ServerValidate_1(sender As Object, e As ServerValidateEventArgs)
        ' [txtAutreDiplome] alanı, [cmbDiplomes]=QZXW2HTMLBW2F1dHJlXQZQ ise boş olmamalıdırX
        e.isvalid=not (cmbDiplomes.selecteditem.text="[Autre]" and txtAutreDiplome.text.trim="") _
            and not (cmbDiplomes.selecteditem.text<>"[Autre]" and cmbDiplomes.selecteditem.text<>"?" and txtAutreDiplome.text.trim<>"")
    End Sub

</script>
....

[CustomValidator] bileşenine bağlı bir doğrulama işlevi iki parametre alır:

  • sender: olayı tetikleyen nesne
  • e: olay. Prosedür, doğrulanmış veriler doğruysa [e.IsValid] özniteliğini true olarak, aksi takdirde false olarak ayarlamalıdır.

Burada yapılan doğrulamalar şunlardır:

  • [cmbDiplomes] açılır listesinin değeri [?] olamaz. Bu, [CompareValidator2] bileşeni tarafından doğrulanır
  • Kullanıcı, [cmbDiplomes] açılır listesinden bir diploma seçer. Seçtiği diploma listede mevcut değilse, listeden [Autre] seçeneğini seçme imkânı vardır. Ardından, [txtAutreDiplome] giriş alanına diplomasını girmelidir. [cmbDiplomes]'te [Autre] seçiliyse, [txtAutreDiplome] alanı boş olmamalıdır. [cmbDiplomes]'te ne [Autre] ne de [?] seçiliyse, [txtAutreDiplome] alanı boş olmalıdır. Bu durum, [CustomValidator1] bileşenine bağlı işlev tarafından kontrol edilir.
  • Mezuniyet yılı, [1900-2004] aralığında olmalıdır. Bu durum, [RangeValidator1] tarafından kontrol edilir. Ancak kullanıcı alana hiçbir şey girmezse, [RangeValidator1]'in doğrulama işlevi kullanılmaz. Bu nedenle, bir içeriğin varlığını doğrulamak için [RequiredFieldValidator2] bileşeni eklenir. Bu genel bir kuraldır. Bir alan boşsa içeriği doğrulanmaz. Doğrulanmasının tek istisnası, alanın [RequiredFieldValidator] bileşeniyle ilişkili olması durumudur.

İşte [Mozilla] tarayıcısında bir yürütme örneği:

Image

[IE6] tarayıcısını kullanırsak, [CustomValidator1] bileşeni için istemci tarafında bir doğrulama işlevi ekleyebiliriz. Bunun için bu bileşen aşağıdaki özelliklere sahiptir:

  • EnableClientScript=true
  • ClientValidationFunction=chkAutreDiplome

[chkAutreDiplome ] işlevi şöyledir:

<head>
    <meta http-equiv="pragma" content="no-cache" />
    <script language="javascript">
        function chkAutreDiplome(source,args){
             // txtAutreDiplome alanının geçerliliğini kontrol eder
            with(document.frmCandidature){
                diplome=cmbDiplomes.options[cmbDiplomes.selectedIndex].text;
                    args.IsValid= !(diplome=="[Autre]" && txtAutreDiplome.value=="")
                        && ! (diplome!="[Autre]" && diplome!="?" && txtAutreDiplome.value!="");
            }
        }
        </script>
</head>

[chkAutreDiplome] işlevi, [CustomValidator1_ServerValidate_1] sunucu işleviyle aynı iki parametreyi alır:

  • kaynak: olayı tetikleyen nesne
  • args: olay. Bu olayın [IsValid] özniteliği vardır; doğrulanmış veriler doğruysa bu öznitelik işlev tarafından true olarak ayarlanmalıdır. false değeri, doğrulama bileşeninin bulunduğu yerde ilgili hata mesajını görüntüler ve form sunucuya gönderilmez.

8.2.5. RegularExpressionValidator

Aşağıdaki [regularexpressionvalidator1.aspx] sayfasını oluşturuyoruz:

Image

no
ad
tür
özellikler
rol
1
txtMel
TextBox
EnableViewState=true
giriş alanı
2
RequiredFieldValidator3
RequiredFieldValidator
ControlToValidate=txtMel
Display=Dynamic
kontrolün doğrulama bileşeni [1]
3
RegularExpressionValidator1
RegularExpressionValidator
ControlToValidate=txtMel
Görüntüleme=Dinamik
kontrolün doğrulama bileşeni [1]
4
btnEnvoyer
Düğme
EnableViewState=false
CausesValidation=true
[submit] düğmesi

Burada bir e-posta adresinin biçimini doğrulamak istiyoruz. Bunu, bir düzenli ifade kullanarak bir alanın geçerliliğini doğrulamaya olanak tanıyan [RegularExpressionValidator] bileşeni ile yapıyoruz. Burada, düzenli ifadenin bir karakter dizisi şablonu olduğunu hatırlatmak isteriz. Dolayısıyla, bir alanın içeriğini bir şablona göre doğrularız. Bir alan boş olduğunda içeriği doğrulanmadığından, e-posta adresinin boş olmadığını doğrulamak için [RequiredFieldValidator] bileşenine de ihtiyacımız var. [RegularExpressionValidator] sınıfı, daha önce incelediğimiz bileşen sınıflarına benzer özelliklere sahiptir:

ControlToValidate
değeri bileşen tarafından kontrol edilmesi gereken alan
EnableClientScript
boole değeri – "true" ise, önceki alanın içeriğinin istemci tarafında da kontrol edilmesi gerektiğini belirtir
ErrorMessage
hata tespit edildiğinde bileşenin görüntülemesi gereken hata mesajı
RegularExpression
[ControlToValidate] alanının içeriğinin karşılaştırılacağı düzenli ifade
Display
görüntüleme modu: Static: hata mesajı görüntülenmese bile alan her zaman mevcuttur; Dynamic: alan yalnızca hata mesajı varsa mevcuttur; None: hata mesajı görüntülenmez. Bu alan diğer bileşenler için de mevcuttur ancak şimdiye kadar kullanılmamıştı.

Bir e-posta adresinin örnek düzenli ifadesi şu şekilde olabilir: \s*[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+\s*

Bir e-posta adresi [champ1.champ2....@champA.champB...] biçimindedir. @ işaretinden önce mutlaka en az bir alan ve sonrasında en az iki alan bulunmalıdır. Bu alanlar alfanümerik karakterlerden ve - işaretinden oluşur. Alfanümerik karakter, \w sembolüyle temsil edilir. [\w-] dizisi, \w karakterini veya - karakterini ifade eder. Bir S dizisinin arkasındaki + işareti, bu dizinin 1 veya daha fazla kez tekrarlanabileceğini; * işareti, 0 veya daha fazla kez tekrarlanabileceğini; ? işareti ise 0 veya 1 kez tekrarlanabileceğini belirtir.

Bir e-posta adresi alanı, [\w-]+ şablonuna karşılık gelir. @ işaretinden önce en az bir alanın ve @ işaretinden sonra nokta (.) ile ayrılmış en az iki alanın bulunması zorunluluğu, şu şablona karşılık gelir: [\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+. Kullanıcının adresin önüne ve arkasına boşluk eklemesine izin verilebilir. Bu boşluklar işleme sırasında kaldırılacaktır. Boşluk dizisi (boş da olabilir) \s* şablonuyla temsil edilir. Dolayısıyla e-posta adresi için düzenli ifade şöyledir: \s*[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+\s*.

Sayfanın sunum kodu ise şu şekildedir:

<html>
<head>
</head>
<body>
    <form runat="server">
        <p align="left">
            Demande du dossier de candidature au DESS
        </p>
        <fieldset>
            <legend>[--Votre adresse électronique où sera envoyé le dossier de candidature--]</legend>
            <table>
                <tbody>
                    <tr>
                        <td>
                            <asp:TextBox id="txtMel" runat="server" Columns="60"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <p>
                                <asp:RequiredFieldValidator id="RequiredFieldValidator3" runat="server" Display="Dynamic" ControlToValidate="txtMel" ErrorMessage="Votre adresse électronique est requise"></asp:RequiredFieldValidator>
                            </p>
                            <p>
                                <asp:RegularExpressionValidator id="RegularExpressionValidator1" runat="server" Display="Dynamic" ControlToValidate="txtMel" ErrorMessage="Votre adresse électronique n'a pas un format valide" ValidationExpression="\s*[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+\s*"></asp:RegularExpressionValidator>
                            </p>
                        </td>
                    </tr>
                </tbody>
            </table>
        </fieldset>
        <p>
            <asp:Button id="btnEnvoyer" runat="server" Text="Envoyer"></asp:Button>
        </p>
    </form>
</body>
</html>

8.2.6. ValidationSummary

Estetik nedenlerle, hata mesajlarını aşağıdaki örnekte olduğu gibi tek bir yerde toplamak isteyebilirsiniz: [summaryvalidator1.aspx]. Burada, önceki tüm örnekleri tek bir sayfada bir araya getirdik:

Image

Tüm doğrulama denetimleri aşağıdaki özelliklere sahiptir:

  • [Display=Dynamic]; bu sayede, hata mesajı boş olan denetimler sayfada yer kaplamaz
  • [EnableClientScript=false], istemci tarafında herhangi bir doğrulama yapılmasını engeller
  • [Text=*]. Hata durumunda görüntülenecek mesaj budur; [ErrorMessage] özniteliğinin içeriği ise aşağıda sunduğumuz [ValidationSummary] denetimi tarafından görüntülenir.

Bu denetim grubu, [vueFormulaire] adlı [Panel] bileşenine yerleştirilmiştir. [vueErreurs] adlı başka bir [Panel] bileşenine ise bir [ValidationSummary] denetimi yerleştiriyoruz:

Image

no
ad
tür
özellikler
rol
1
ValidationSummary1
ValidationSummary
HeaderText=Aşağıdaki hatalar oluştu, EnableClientScript=false, ShowSummary=true
sayfadaki tüm doğrulama denetimlerinin hatalarını gösterir
2
lnkErreursToFormulaire
LinkButton
CausesValidation=false
formuna geri dönüş bağlantısı

[lnkErreursToFormulaire] bağlantısı için, bu bağlantı doğrulanacak herhangi bir değer göndermediğinden doğrulama etkinleştirilmesine gerek yoktur.

Tüm veriler geçerli olduğunda, kullanıcıya aşağıdaki [infos] görünümü sunulur:

Image

1

no
ad
tür
özellikler
rol
1
lblInfo
Etiket
 
kullanıcıya yönelik bilgilendirme mesajı

Bu sayfanın sunum kodu şöyledir:

<html>
<head>
</head>
<body>
    <form runat="server">
        <p align="left">
            Demande du dossier de candidature au DESS 
        </p>
        <p>
            <hr />
            <asp:panel id="vueErreurs" runat="server">
                <p align="left">
                    <asp:ValidationSummary id="ValidationSummary1" runat="server" ShowMessageBox="True" BorderColor="#C04000" BorderWidth="1px" BackColor="#FFFFC0" HeaderText="Les erreurs suivantes se sont produites"></asp:ValidationSummary>
                </p>
                <p>
                    <asp:LinkButton id="lnkErreursToFormulaire" onclick="lnkErreursToFormulaire_Click" runat="server" CausesValidation="False">Retour au formulaire</asp:LinkButton>
                </p>
            </asp:panel>
            <asp:panel id="vueFormulaire" runat="server">
....
                    <asp:Button id="btnEnvoyer" onclick="btnEnvoyer_Click" runat="server" Text="Envoyer"></asp:Button>
                </p>
            </asp:panel>
        <asp:panel id="vueInfos" runat="server">
            <asp:Label id="lblInfo" runat="server"></asp:Label>
        </asp:panel>
    </form>
</body>
</html>

İşte elde edilen sonuçlardan bazı örnekler. Herhangi bir değer girmeden [formulaire] görünümünü onaylıyoruz:

Image

[Envoyer] düğmesi bize şu yanıtı veriyor:

Image

Görüntülenen, [erreurs] görünümüdür. Forma geri dönme bağlantısını kullanırsak, formu şu durumda buluruz:

Image

Bu, [formulaire] görünümüdür. Hatalı verilerin yanında [*] karakteri dikkat çekiyor. Burada, doğrulama denetimlerinin [Text] alanı görüntülenmiştir. Alanları doğru şekilde doldurursak, [infos] görünümünü elde ederiz:

Image

Sayfanın kontrol kodu şöyledir:

<%@ Page Language="VB" %>
<script runat="server">

     ' sayfa yüklendiğinde yürütülen işlem
    Sub page_Load(sender As Object, e As EventArgs)
        ' ilk istekte [formulaire] görünümü sunulur
        if not ispostback then
            afficheVues(true,false,false)
        end if
    end sub

    sub afficheVues(byval formulaireVisible as boolean, _
        erreursVisible as boolean, infosVisible as boolean)
         ' görünüm kümesi
        vueFormulaire.visible=formulaireVisible
        vueErreurs.visible=erreursVisible
        vueInfos.visible=infosVisible
    end sub

    Sub CustomValidator1_ServerValidate(sender As Object, e As ServerValidateEventArgs)
...
    End Sub

    Sub CustomValidator2_ServerValidate(sender As Object, e As ServerValidateEventArgs)
...
    End Sub

    Sub CustomValidator1_ServerValidate_1(sender As Object, e As ServerValidateEventArgs)
...
    End Sub

    Sub lnkErreursToFormulaire_Click(sender As Object, e As EventArgs)
        ' form görünümünü görüntüler
        afficheVues(true,false,false)
         ' geçerlilik denetimlerini yeniden yapar
        Page.validate
    End Sub

    Sub btnEnvoyer_Click(sender As Object, e As EventArgs)
        ' sayfa geçerli mi?
        if not Page.IsValid then
            ' [erreurs] görünümü görüntülenir
            afficheVues(false,true,false)
        else
             ' aksi takdirde [infos] görünümünü görüntüler
            lblInfo.Text="Le dossier de candidature au DESS IAIE a été envoyé à l'adresse ["+ _
                        txtMel.Text + "]. Nous vous en souhaitons bonne réception.<br><br>Le secrétariat du DESS."
            afficheVues(false,false,true)
        end if
    end sub

</script>
<html>
...
</html>
  • Müşterinin her isteğinde yürütülen [Page_Load] prosedüründe, [formulaire] görünümünü görüntüleriz; diğerleri ise gizlenir. Bu işlem yalnızca ilk istekte gerçekleştirilir. Prosedür, üç görünümü görüntülemek veya gizlemek için üç boole değeri aktarıldığı [afficheVues] yardımcı prosedürünü çağırır.
  • [btnEnvoyer_Click] yordamı çağrıldığında, veri doğrulamaları tamamlanmış olur. [btnEnvoyer] düğmesi, [CausesValidation=true] özelliğine sahiptir ve bu özellik veri doğrulamasını zorlar. Tüm doğrulama denetimleri yürütülmüş ve [IsValid] özelliği ayarlanmıştır. Bu özellik, denetim tarafından doğrulanan verinin geçerli olup olmadığını gösterir. Ayrıca, sayfanın kendisinin [IsValid] özelliği de ayarlanmıştır. Bu özellik, yalnızca sayfanın tüm doğrulama denetimlerinin [IsValid] özelliğinin değeri [vrai] ise [vrai] olarak ayarlanır. Böylece [btnEnvoyer_Click] prosedürü, sayfanın geçerli olup olmadığını kontrol ederek başlar. Sayfa geçersizse, [erreurs] görünümü görüntülenir. Bu görünüm, tüm denetimlerin [ErrorMessage] özniteliklerini alan [ValidationSummary] denetimini içerir (yukarıdaki ekran görüntüsüne bakınız). Sayfa geçerliyse, bir bilgi mesajıyla birlikte [infos] görünümü görüntülenir.
  • [lnkErreursToFormulaire_Click] prosedürü, [formulaire] görünümünü onaylandığı haliyle görüntülemekle görevlidir. [EnableViewState=true] özelliğine sahip [formulaire] görünümündeki tüm giriş alanlarının durumu otomatik olarak yeniden oluşturulur. İlginç bir şekilde, doğrulama bileşenlerinin durumu ise geri yüklenmez. Aslında, [erreurs] görünümüne geri döndüğümüzde, hatalı denetimlerin [Text] alanını göstermesi beklenirdi. Ancak durum böyle değildir. Bu nedenle, sayfanın [Page.Validate] yöntemini kullanarak verilerin doğrulanmasını zorladık. Bu işlem, [vueFormulaire] paneli görünür hale getirildikten sonra yapılmalıdır. Dolayısıyla toplamda iki doğrulama işlemi söz konusudur. Pratikte bu durumdan kaçınılmalıdır. Bu örnekte ise sayfa doğrulamasıyla ilgili yeni kavramları tanıtma fırsatı bulduk.

8.3. ListControl bileşenleri ve veri bağlama

İncelenen sunucu bileşenlerinden bazıları, bir değer listesinin görüntülenmesini sağlar (DropDownList, ListBox). Henüz tanıtmadığımız diğer bileşenler ise HTML tablolarında birden fazla değer listesinin görüntülenmesini sağlar. Hepsi için, program yoluyla liste değerlerini ilgili bileşene tek tek eşleştirmek mümkündür. Ayrıca, [Array], [ArrayList], [DataSet], [HashTable] gibi daha karmaşık nesneleri bu bileşenlere eşleştirmek de mümkündür, ... gibi daha karmaşık nesneler de bu bileşenlere ilişkilendirilebilir; bu da verileri bileşene bağlayan kodu basitleştirir. Bu ilişkilendirmeye veri bağlantısı denir.

[ListControl] sınıfından türetilen tüm bileşenler bir veri listesiyle ilişkilendirilebilir. Bunlar, [DropDownList], [ListBox], [CheckButtonList] ve [RadioButtonList] bileşenleridir. Bu bileşenlerin her biri bir veri kaynağına bağlanabilir. Veri kaynağı çeşitli olabilir: [Array], [ArrayList], [DataTable], [DataSet], [HashTable],...., genel olarak IEnumerable, ICollection, IListSource arayüzlerinden birini uygulayan bir nesne. Bunlardan sadece birkaçını ele alacağız. [DataSet] nesnesi, ilişkisel bir veritabanının görüntü nesnesidir. Dolayısıyla, ilişkilerle birbirine bağlanmış bir dizi tablodan oluşur. [DataTable] nesnesi ise bu tür bir tabloyu temsil eder. Veri kaynağı, [ListControl] nesnesinin her bir [Item] elemanının [Text] ve [Value] özelliklerini belirler. T, [Text]'in değeri ve V, [Value]'in değeri ise, [ListControl]'in her bir elemanı için oluşturulan HTML etiketi şöyledir:

DropDownList, ListBox
<option value="V">T</option>
CheckButtonList
<input type="checkbox" value="V">T
RadioButtonList
<input type="radio" value="V">T

[ListControl] bileşeninin bir veri kaynağına bağlanması aşağıdaki özellikler aracılığıyla gerçekleştirilir:

DataSource
bir veri kaynağı [Array], [ArrayList], [DataTable], [DataSet], [HashTable], ...
DataMember
veri kaynağı bir [DataSet] ise, bu, veri kaynağı olarak kullanılacak tablonun adını temsil eder. Bu durumda gerçek veri kaynağı bir tablodur.
DataTextField
veri kaynağı bir tablo olduğunda ([DataTable], [DataSet]), [ListControl] öğelerinin [Text] alanına değerlerini sağlayacak tablodaki sütunun adını temsil eder
DataValueField
veri kaynağı bir tablo olduğunda ([DataTable],[DataSet]), [ListControl] öğelerinin [Value] alanına değerlerini sağlayacak tablonun sütun adını temsil eder

Bir [ListControl] bileşeninin bir veri kaynağına eklenmesi, bileşeni veri kaynağının değerleriyle başlatmaz. Bunu gerçekleştiren işlem [ListControl].DataBind'tir.

Veri kaynağının türüne bağlı olarak, bu kaynağın bir [ListControl] bileşenine eklenmesi farklı şekillerde gerçekleşir:

Array A
[ListControl].DataSource=A
[ListControl] öğelerinin [Text] ve [Value] alanlarının değerleri, A öğelerinin değerleri olacaktır
ArrayList AL
[ListControl].DataSource=AL
[ListControl] öğelerinin [Text] ve [Value] alanlarının değerleri, AL öğelerinin değerleri olacaktır
DataTable DT
[ListControl].DataSource=DT, [ListControl].DataTextField="col1", [ListControl]. DatavalueField ="col2"
burada col1 ve col2, DT tablosundaki iki sütundur. [ListControl] öğelerinin [Text] ve [Value] alanlarının değerleri, DT tablosundaki col1 ve col2 sütunlarının değerleri olacaktır
DataSet DS
[ListControl].DataSource=DS, [ListControl].DataSource="table", burada "table", DS'teki tablolardan birinin adıdır.
[ListControl].DataTextField="col1", [ListControl]. DatavalueField ="col2"; burada col1 ve col2, "table" tablosundaki iki sütundur. [ListControl] öğelerinin [Text] ve [Value] alanlarının değerleri, "table" tablosundaki col1 ve col2 sütunlarının değerleri olacaktır
HashTable HT
[ListControl].DataSource=HT, [ListControl].DataTextField="key", [ListControl]. DatavalueField ="value" burada [key] ve [value], sırasıyla HT'in anahtarları ve değerleridir.

Bu bilgileri aşağıdaki [databind1.aspx] örneğinde uygulayalım:

Burada, her biri [DropDownList], [ListBox], [CheckBoxList] ve [RadioButtonList] türünde dört denetim içeren beş veri bağlantısı bulunmaktadır. İncelenen bu beş bağlantı, veri kaynakları bakımından birbirinden farklıdır:

bağlantı
veri kaynağı
1
Dizi
2
ArrayList
3
DataTable
4
DataSet
5
HashTable

8.3.1. Bileşenlerin sunum kodu

Bağlantı 1'deki denetimlerin sunum kodu şöyledir:

<td>
<asp:DropDownList id="DropDownList1" runat="server"></asp:DropDownList>
</td>
<td>
<asp:ListBox id="ListBox1" runat="server" SelectionMode="Multiple"></asp:ListBox>
</td>
<td>
<asp:CheckBoxList id="CheckBoxList1" runat="server"></asp:CheckBoxList>
</td>
<td>
<asp:RadioButtonList id="RadioButtonList1" runat="server"></asp:RadioButtonList>
</td>

2 ile 5 arasındaki bağlantıların numarası, bağlantı numarası dışında aynıdır.

8.3.2. Dizi türündeki bir veri kaynağına bağlantı

Yukarıdaki dört [ListBox] kontrolünün bağlantısı, kontrol kodundaki [Page_Load] prosedüründe şu şekilde yapılır:

' genel veriler
dim textes() as string={"un","deux","trois","quatre"}
dim valeurs() as string={"1","2","3","4"}
dim myDataListe as new ArrayList
dim myDataTable as new DataTable("table1")
dim myDataSet as new DataSet
dim myHashTable as new HashTable

' sayfa yüklendiğinde yürütülen prosedür
Sub page_Load(sender As Object, e As EventArgs)
    if not IsPostBack then
      ' bileşenlere bağlanacak verilerin kaynakları oluşturulur
      createDataSources
       ' bir tabloya bağlanma [Array]
      bindToArray
       ' bir listeye bağlanma [ArrayList]
      bindToArrayList
       ' bir tabloya bağlantı [DataTable]
      bindToDataTable
       ' bir veri grubuna bağlantı [DataSet]
      bindToDataSet
       ' bir sözlüğe bağlantı [HashTable]
      bindToHashTable
    end if
End Sub

sub createDataSources
   ' bileşenlere bağlanacak veri kaynaklarını oluşturur
  ' arraylist
  dim i as integer
  for i=0 to textes.length-1
    myDataListe.add(textes(i))
  next
   ' veri tablosu
   ' iki sütunu tanımlanır
  myDataTable.Columns.Add("id",Type.GetType("System.Int32"))
  myDataTable.Columns.Add("texte",Type.GetType("System.String"))
  ' tablo doldurulur
  dim ligne as DataRow
  for i=0 to textes.length-1
    ligne=myDataTable.NewRow
    ligne("id")=i
    ligne("texte")=textes(i)
    myDataTable.Rows.Add(ligne)
  next
   ' veri kümesi - tek bir tablo
  myDataSet.Tables.Add(myDataTable)
  ' hashtable
  for i=0 to textes.length-1
    myHashTable.add(valeurs(i),textes(i))
  next
end sub

' tablo bağlantısı
sub bindToArray
         ' bileşenlerle ilişkilendirme
        with DropDownList1
            .DataSource=textes
            .DataBind
        end with
        with ListBox1
            .DataSource=textes
            .DataBind
        end with
        with CheckBoxList1
            .DataSource=textes
            .DataBind
        end with
        with RadioButtonList1
            .DataSource=textes
            .DataBind
        end with
        ' öğelerin seçimi
        ListBox1.Items(1).Selected=true
        ListBox1.Items(3).Selected=true
        CheckBoxList1.Items(0).Selected=true
        CheckBoxList1.Items(3).Selected=true
        DropDownList1.SelectedIndex=2
        RadioButtonList1.SelectedIndex=1
end sub

sub bindToArrayList
....
end sub

sub bindToDataTable
...
end sub

sub bindToDataSet
...
end sub

Kontrollerin verilere bağlanması burada yalnızca ilk istekte gerçekleştirilir. Daha sonra kontroller, [VIEWSTATE] mekanizması aracılığıyla öğelerini koruyacaktır. Bağlantı, [bindToArray] prosedüründe gerçekleştirilir. Veri kaynağı [Array] türü olduğundan, [ListControl] bileşenlerinin yalnızca [DataSource] alanı başlatılır. Kontrolün, ilişkili veri kaynağının değerleriyle doldurulması [ListControl].DataBind yöntemi ile gerçekleştirilir. Ancak bundan sonra [ListControl] nesneleri öğelere sahip olur. Bu noktada bunlardan bazıları seçilebilir.

8.3.3. ArrayList türündeki bir veri kaynağına bağlanma

[myDataListe] veri kaynağı, [createDataSources] yordamında başlatılır:

' genel veriler
dim textes() as string={"un","deux","trois","quatre"}
dim myDataListe as new ArrayList
..

' sayfa yüklendiğinde yürütülen prosedür
Sub page_Load(sender As Object, e As EventArgs)
    if not IsPostBack then
      ' bileşenlere bağlanacak veri kaynakları oluşturulur
      createDataSources
...
    end if
End Sub

sub createDataSources
   ' bileşenlere bağlanacak veri kaynakları oluşturulur
  ' arraylist
  dim i as integer
  for i=0 to textes.length-1
    myDataListe.add(textes(i))
  next
...
end sub

Bağlantı 2'deki dört [ListBox] kontrolünün, kontrol kodundaki [bindToArrayList] prosedüründe aşağıdaki şekilde bağlanması gerekir:

' arraylist bağlantısı
sub bindToArrayList
         ' bileşenlere ilişkilendirme
        with DropDownList2
            .DataSource=myDataListe
            .DataBind
        end with
        with ListBox2
            .DataSource=myDataListe
            .DataBind
        end with
        with CheckBoxList2
            .DataSource=myDataListe
            .DataBind
        end with
        with RadioButtonList2
            .DataSource=myDataListe
            .DataBind
        end with
        ' öğelerin seçimi
        ListBox2.Items(1).Selected=true
        ListBox2.Items(3).Selected=true
        CheckBoxList2.Items(0).Selected=true
        CheckBoxList2.Items(3).Selected=true
        DropDownList2.SelectedIndex=2
        RadioButtonList2.SelectedIndex=1
end sub

Veri kaynağı [ArrayList] türü olduğundan, yalnızca [ListControl] bileşenlerinin [DataSource] alanı başlatılır.

8.3.4. DataTable türündeki veri kaynağı

[myDataTable] veri kaynağı, [createDataSources] yordamında başlatılır:

' genel veriler
dim textes() as string={"un","deux","trois","quatre"}
dim myDataTable as new DataTable("table1")
...

' sayfa yüklendiğinde yürütülen prosedür
Sub page_Load(sender As Object, e As EventArgs)
    if not IsPostBack then
      ' bileşenlere bağlanacak veri kaynakları oluşturulur
      createDataSources
...
    end if
End Sub

sub createDataSources
   ' bileşenlere bağlanacak veri kaynakları oluşturulur
...
   ' veri tablosu
   ' iki sütunu tanımlanır
  myDataTable.Columns.Add("id",Type.GetType("System.Int32"))
  myDataTable.Columns.Add("texte",Type.GetType("System.String"))
  ' tabloyu dolduruyoruz
  dim ligne as DataRow
  for i=0 to textes.length-1
    ligne=myDataTable.NewRow
    ligne("id")=i
    ligne("texte")=textes(i)
    myDataTable.Rows.Add(ligne)
  next
...
end sub

İlk olarak, [DataTable] adlı bir nesne oluşturuyoruz; bu nesne, [id] ve [texte] adlı iki sütundan oluşuyor. [id] sütunu, [ListControl] öğelerinin [Value] alanını dolduracak ve [texte] sütunu ise [Text] alanlarını dolduracaktır. İki sütunlu [DataTable]'in oluşturulması şu şekilde yapılır:

  myDataTable.Columns.Add("id",Type.GetType("System.Int32"))
  myDataTable.Columns.Add("texte",Type.GetType("System.String"))

Böylece iki sütunlu bir tablo oluşturulur:

  • "id" adlı ilk sütun tamsayı türündedir
  • ikincisi "metin" olarak adlandırılır ve karakter dizisi türündedir

Tablonun yapısı oluşturulduktan sonra, aşağıdaki kodla doldurabiliriz:

  dim ligne as DataRow
  for i=0 to textes.length-1
    ligne=myDataTable.NewRow
    ligne("id")=i
    ligne("texte")=textes(i)
    myDataTable.Rows.Add(ligne)
  next

[id] sütunu [0,1,..,n] tamsayılarını içerecekken, [texte] sütunu [data] tablosundaki değerleri içerecektir. Bu işlem tamamlandığında, [dataListe] tablosu doldurulur. Bağlantı 3’teki dört [ListBox] kontrolünün birbirine bağlanması, kontrol kodundaki [bindToDataTable] prosedüründe şu şekilde gerçekleştirilir:

sub bindToDataTable
         ' bileşenlerle ilişkilendirme
        with DropDownList3
            .DataSource=myDataTable
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        with ListBox3
            .DataSource=myDataTable
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        with CheckBoxList3
            .DataSource=myDataTable
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        with RadioButtonList3
            .DataSource=myDataTable
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        ' öğelerin seçilmesi
        ListBox3.Items(1).Selected=true
        ListBox3.Items(3).Selected=true
        CheckBoxList3.Items(0).Selected=true
        CheckBoxList3.Items(3).Selected=true
        DropDownList3.SelectedIndex=2
        RadioButtonList3.SelectedIndex=1
end sub

Her bir [ListControl] bileşeni, her birine aşağıdakiler atanarak [myDataTable] kaynağına bağlanır:

            .DataSource= myDataTable
            .DataValueField="id"
            .DataTextField="texte"

[myDataTable] tablosu veri kaynağıdır. Bu tablonun [id] sütunu, bileşen öğelerinin [Value] alanlarını doldururken, [texte] sütunu ise [Text] alanlarını dolduracaktır.

8.3.5. DataSet türündeki veri kaynağı

[myDataSet] veri kaynağı, [createDataSources] yordamında başlatılır:

' genel veriler
dim myDataTable as new DataTable("table1")
dim myDataSet as new DataSet
...


' sayfa yüklendiğinde yürütülen prosedür
Sub page_Load(sender As Object, e As EventArgs)
    if not IsPostBack then
      ' bileşenlere bağlanacak veri kaynakları oluşturulur
      createDataSources
...
    end if
End Sub

sub createDataSources
   ' bileşenlere bağlanacak veri kaynakları oluşturulur
   ' veri kümesi - tek bir tablo
  myDataSet.Tables.Add(myDataTable)
...
end sub

Bir [DataSet] nesnesi, [DataTable] türündeki bir dizi tabloyu temsil eder. Daha önce oluşturulan [myDataTable] tablosu, [DataSet]'e eklenir. Bağlantı 4'teki dört [ListBox] kontrolünün birbirine bağlanması, kontrol kodundaki [bindToDataSet] yordamında şu şekilde gerçekleştirilir:

sub bindToDataSet
         ' bileşenlerle ilişkilendirme
        with DropDownList4
            .DataSource=myDataSet
            .DataMember="table1"
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        with ListBox4
            .DataSource=myDataSet
            .DataMember="table1"
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        with CheckBoxList4
            .DataSource=myDataSet
            .DataMember="table1"
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        with RadioButtonList4
            .DataSource=myDataSet
            .DataMember="table1"
            .DataValueField="id"
            .DataTextField="texte"
            .DataBind
        end with
        ' öğelerin seçimi
        ListBox4.Items(1).Selected=true
        ListBox4.Items(3).Selected=true
        CheckBoxList4.Items(0).Selected=true
        CheckBoxList4.Items(3).Selected=true
        DropDownList4.SelectedIndex=2
        RadioButtonList4.SelectedIndex=1
end sub

Her bir [ListControl] bileşeni, veri kaynağına şu şekilde bağlanmıştır:

            .DataSource= myDataSet
            .DataMember="table1"
            .DataValueField="id"
            .DataTextField="texte"

[myDataSet] veri grubu, veri kaynağıdır. Bu veri grubu birden fazla tablo içerebileceğinden, [DataMember]'te kullanılacak tablonun adı belirtilir. Bu tablonun [id] sütunu, bileşen öğelerinin [Value] alanlarını doldururken, [texte] sütunu ise [Text] alanlarını dolduracaktır.

8.3.6. HashTable türündeki veri kaynağı

[myHashTable] veri kaynağı, [createDataSources] yordamında başlatılır:

' genel veriler
dim textes() as string={"un","deux","trois","quatre"}
dim valeurs() as string={"1","2","3","4"}
dim myHashTable as new HashTable
...

' sayfa yüklendiğinde yürütülen prosedür
Sub page_Load(sender As Object, e As EventArgs)
    if not IsPostBack then
      ' bileşenlere bağlanacak veri kaynakları oluşturulur
      createDataSources
...
    end if
End Sub

sub createDataSources
   ' bileşenlere bağlanacak veri kaynakları oluşturulur
...
  ' hash tablosu
  for i=0 to textes.length-1
    myHashTable.add(valeurs(i),textes(i))
  next
end sub

[myHashTable] sözlüğü, "anahtar" ve "değer" adlı iki sütundan oluşan bir tablo olarak görülebilir. [key] sütunu sözlüğün anahtarlarını, [value] sütunu ise bunlara ilişkin değerleri temsil eder. [key] sütunu, [valeurs] tablosunun içeriğinden, [value] sütunu ise [textes] tablosunun içeriğinden oluşur. Bu kaynağın denetimlerle ilişkilendirilmesi, [bindToHashTable] yordamında gerçekleştirilir:

sub bindToHashTable
         ' bileşenlerle ilişkilendirme
        with DropDownList5
            .DataSource=myHashTable
            .DataValueField="key"
            .DataTextField="value"
            .DataBind
        end with
        with ListBox5
            .DataSource=myHashTable
            .DataValueField="key"
            .DataTextField="value"
            .DataBind
        end with
        with CheckBoxList5
            .DataSource=myHashTable
            .DataValueField="key"
            .DataTextField="value"
            .DataBind
        end with
        with RadioButtonList5
            .DataSource=myHashTable
            .DataValueField="key"
            .DataTextField="value"
            .DataBind
        end with
        ' öğelerin seçilmesi
        ListBox5.Items(1).Selected=true
        ListBox5.Items(3).Selected=true
        CheckBoxList5.Items(0).Selected=true
        CheckBoxList5.Items(3).Selected=true
        DropDownList5.SelectedIndex=2
        RadioButtonList5.SelectedIndex=1
end sub

Her bir bileşen için bağlantı şu komutlarla yapılır:

            .DataSource=myHashTable
            .DataValueField="key"
            .DataTextField="value"

Veri kaynağı, [myHashTable] sözlüğüdür. Kontrol değerleri, sözlüğün [key] sütunundan, metinler ise [value] sütunundan sağlanır. Sözlük öğelerinin kontrollere eklenmesi, öncelikle rastgele olan anahtar sırasına göre yapılır.

8.3.7. Ad alanlarını içe aktarma yönergeleri

Bir dizi ad alanı, ASP.NET sayfasına otomatik olarak içe aktarılır. Ancak, [DataTable] ve [DataSet] sınıflarının bulunduğu "System.Data" için durum böyle değildir. Bu nedenle bu sınıfın da içe aktarılması gerekir. Bu işlem şu şekilde yapılır:

<%@ Page Language="VB" %>
<%@ import Namespace="System.Data" %>
<script runat="server">
...
</script>
<html>
...
</html>

8.4. DataGrid bileşeni ve veri bağlantısı

[DataGrid] bileşeni, verileri tablo şeklinde görüntülemeye olanak tanır, ancak bu basit görüntülemenin çok ötesine geçer:

  • tablonun "görsel sunumunu" hassas bir şekilde ayarlama imkanı sunar
  • veri kaynağının güncellenmesine olanak tanır

[DataGrid] bileşeni, hem güçlü hem de karmaşık bir bileşendir. Bu bileşeni adım adım tanıtacağız.

8.4.1. Bir Array veri kaynağının görüntülenmesi, ArrayList, DataTable, DataSet

[DataGrid] bileşeni, HTML tablosunda [Array], [ArrayList], [DataTable] ve [DataSet] türündeki veri kaynaklarını görüntülemenizi sağlar. Bu dört veri türü için, kaynağı [DataGrid] bileşeninin [DataSource] özelliğine atamanız yeterlidir:

DataSource
bir veri kaynağı [Array], [ArrayList], [DataTable], [DataSet], ...
DataMember
Veri kaynağı bir [DataSet] ise, bu alan veri kaynağı olarak kullanılacak tablonun adını temsil eder. Bu durumda gerçek veri kaynağı bir tablodur. Bu alan doldurulmazsa, [DataSet]'teki tüm tablolar görüntülenir.

Şimdi, bir [DataGrid]'in dört farklı veri kaynağıyla ilişkilendirildiğini gösteren [datagrid1.aspx] sayfasını sunuyoruz:

Image

Sayfa, [WebMatrix] kullanılarak aşağıdaki şekilde oluşturulmuş dört adet [DataGrid] bileşeni içerir. Bileşen, [Design] sekmesindeki yerine yerleştirilir:

Image

Ardından genel bir HTML tablosu çizilir. Bir [DataGrid]'in özellikleri tasarım aşamasında tanımlanabilir. Burada, biçimlendirme özelliklerini bu şekilde tanımlıyoruz. Bunun için, yapılandırılacak [DataGrid]'i seçiyoruz. Özellikleri sağ alt köşedeki bir pencerede görüntülenir:

Image

Yukarıdaki iki bağlantıyı da kullanacağız. [Générateur de propriétés] bağlantısı, [DataGrid]'in temel özelliklerine erişim sağlar:

Image

Dört bileşen olan [DataGrid] için [Afficher l'en-tête] seçeneğinin işaretini kaldırıp sayfayı onaylıyoruz. Diğer bağlantı olan [Mise en forme automatique] ise görüntülenecek HTML tablosu için çeşitli stiller arasından seçim yapmamızı sağlar:

Image

i numaralı [DataGrid] için [couleur i]'i seçiyoruz. Bu tasarım seçimleri, sayfanın sunum koduna yansıtılır:

<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Liaison de données avec un DataGrid 
        </p>
        <hr />
        <p>
            <table>
                <tbody>
                </tbody>
            </table>
            <table border="1">
                <tbody>
                    <tr>
                        <td>
                            Array</td>
                        <td>
                            ArrayList</td>
                        <td>
                            DataTable</td>
                        <td>
                            DataSet</td>
                    </tr>
                    <tr>
                        <td>
                            <asp:DataGrid id="DataGrid1" runat="server" ShowHeader="False" CellPadding="4" BackColor="White" BorderColor="#CC9966" BorderWidth="1px" BorderStyle="None">
                                <FooterStyle forecolor="#330099" backcolor="#FFFFCC"></FooterStyle>
                                <HeaderStyle font-bold="True" forecolor="#FFFFCC" backcolor="#990000"></HeaderStyle>
                                <PagerStyle horizontalalign="Center" forecolor="#330099" backcolor="#FFFFCC"></PagerStyle>
                                <SelectedItemStyle font-bold="True" forecolor="#663399" backcolor="#FFCC66"></SelectedItemStyle>
                                <ItemStyle forecolor="#330099" backcolor="White"></ItemStyle>
                            </asp:DataGrid>
                        </td>
                        <td>
                            <asp:DataGrid id="DataGrid2" runat="server" ShowHeader="False" CellPadding="4" BackColor="White" BorderColor="#3366CC" BorderWidth="1px" BorderStyle="None">
                                <FooterStyle forecolor="#003399" backcolor="#99CCCC"></FooterStyle>
                                <HeaderStyle font-bold="True" forecolor="#CCCCFF" backcolor="#003399"></HeaderStyle>
                                <PagerStyle horizontalalign="Left" forecolor="#003399" backcolor="#99CCCC" mode="NumericPages"></PagerStyle>
                                <SelectedItemStyle font-bold="True" forecolor="#CCFF99" backcolor="#009999"></SelectedItemStyle>
                                <ItemStyle forecolor="#003399" backcolor="White"></ItemStyle>
                            </asp:DataGrid>
                        </td>
                        <td>
                            <asp:DataGrid id="DataGrid3" runat="server" ShowHeader="False" CellPadding="3" BackColor="#DEBA84" BorderColor="#DEBA84" BorderWidth="1px" BorderStyle="None" CellSpacing="2">
                                <FooterStyle forecolor="#8C4510" backcolor="#F7DFB5"></FooterStyle>
                                <HeaderStyle font-bold="True" forecolor="White" backcolor="#A55129"></HeaderStyle>
                                <PagerStyle horizontalalign="Center" forecolor="#8C4510" mode="NumericPages"></PagerStyle>
                                <SelectedItemStyle font-bold="True" forecolor="White" backcolor="#738A9C"></SelectedItemStyle>
                                <ItemStyle forecolor="#8C4510" backcolor="#FFF7E7"></ItemStyle>
                            </asp:DataGrid>
                        </td>
                        <td>
                            <asp:DataGrid id="DataGrid4" runat="server" ShowHeader="False" CellPadding="3" BackColor="White" BorderColor="#E7E7FF" BorderWidth="1px" BorderStyle="None" GridLines="Horizontal">
                                <FooterStyle forecolor="#4A3C8C" backcolor="#B5C7DE"></FooterStyle>
                                <HeaderStyle font-bold="True" forecolor="#F7F7F7" backcolor="#4A3C8C"></HeaderStyle>
                                <PagerStyle horizontalalign="Right" forecolor="#4A3C8C" backcolor="#E7E7FF" mode="NumericPages"></PagerStyle>
                                <SelectedItemStyle font-bold="True" forecolor="#F7F7F7" backcolor="#738A9C"></SelectedItemStyle>
                                <AlternatingItemStyle backcolor="#F7F7F7"></AlternatingItemStyle>
                                <ItemStyle forecolor="#4A3C8C" backcolor="#E7E7FF"></ItemStyle>
                            </asp:DataGrid>
                        </td>
                    </tr>
                </tbody>
            </table>
        </p>
        <asp:Button id="Button1" runat="server" Text="Envoyer"></asp:Button>
    </form>
</body>
</html>

Tasarım modunda yalnızca biçimlendirme özelliklerini belirledik. Dört bileşene verileri atadığımız yer kontrol kodudur:

<%@ Page Language="VB" %>
<%@ import Namespace="system.data" %>
<script runat="server">

     ' genel veriler
        dim textes1() as string={"un","deux","trois","quatre"}
        dim textes2() as string={"one","two","three","for"}
        dim valeurs() as string={"1","2","3","4"}
        dim myDataListe as new ArrayList
        dim myDataTable as new DataTable("table1")
        dim myDataSet as new DataSet

        ' sayfa yüklendiğinde yürütülen prosedür
        Sub page_Load(sender As Object, e As EventArgs)
            if not IsPostBack then
              ' bileşenlere bağlanacak veri kaynakları oluşturulur
              createDataSources
               ' bir tabloya bağlanma [Array]
              bindToArray
               ' bir listeye bağlanma [ArrayList]
              bindToArrayList
               ' bir tabloya bağlantı [DataTable]
              bindToDataTable
               ' bir veri grubuna bağlantı [DataSet]
              bindToDataSet
            end if
        End Sub

        sub createDataSources
           ' bileşenlere bağlanacak veri kaynaklarını oluşturur
          ' arraylist
          dim i as integer
          for i=0 to textes1.length-1
            myDataListe.add(textes1(i))
          next
           ' datatable
           ' iki sütunu tanımlanır
          myDataTable.Columns.Add("id",Type.GetType("System.Int32"))
          myDataTable.Columns.Add("texte1",Type.GetType("System.String"))
          myDataTable.Columns.Add("texte2",Type.GetType("System.String"))
          ' tablo doldurulur
          dim ligne as DataRow
          for i=0 to textes1.length-1
            ligne=myDataTable.NewRow
            ligne("id")=valeurs(i)
            ligne("texte1")=textes1(i)
            ligne("texte2")=textes2(i)
            myDataTable.Rows.Add(ligne)
          next
           ' veri kümesi - tek bir tablo
          myDataSet.Tables.Add(myDataTable)
        end sub

        ' dizi bağlantısı
        sub bindToArray
          with DataGrid1
            .DataSource=textes1
            .DataBind
          end with
        end sub

        ' dizi listesi bağlantısı
        sub bindToArrayList
          with DataGrid2
            .DataSource=myDataListe
            .DataBind
          end with
        end sub

        ' veri tablosu bağlantısı
        sub bindToDataTable
          with DataGrid3
            .DataSource=myDataTable
            .DataBind
          end with
        end sub

        ' veri kümesi bağlantısı
        sub bindToDataSet
          with DataGrid4
            .DataSource=myDataSet
            .DataBind
          end with
        end sub

</script>
<html>
...
</html>

Kod, önceki örnektekine oldukça benziyor, bu nedenle bu konuda özel bir açıklama yapmayacağız. Ancak, veri bağlamanın nasıl yapıldığına dikkat edelim. Dört kontrolün her biri için aşağıdaki dizi yeterlidir:

          with [DataGrid]
            .DataSource=[source de données]
            .DataBind
          end with

burada [source de données], [Array], [ArrayList], [DataTable] veya [DataSet] türündedir. Görüldüğü gibi, burada tablolar halinde veri görüntülemek için güçlü bir araç söz konusudur:

  • biçimlendirme, tasarım aşamasında [WebMatrix] veya herhangi bir IDE ile yapılır
  • veri bağlantısı ise kodda yapılır. [WebMatrix] ile, veri kaynağı bir SQL sunucu veritabanı veya bir ACCESS veritabanı ise, bu bağlantı tasarım aşamasında da yapılabilir. Bu durumda, sayfaya [SqlDataSource] veya [AccessDataSource] türünde bir bileşen yerleştirilir. Bu bileşen, tasarım aşamasında duruma göre bir SQL sunucu veritabanına veya bir ACCESS veritabanına bağlanabilir. Bir [DataGrid] bileşeninin [DataSource] özelliğine, fiziksel bir kaynağa bağlı bir [SqlDataSource] veya [AccessDataSource] nesnesi atanırsa, tasarım modunda [DataGrid] bileşeninde gerçek veriler görünür.

8.5. ViewState veri listesi bileşenleri

Burada, veri listesi bileşenleri için [VIEWSATE] mekanizmasını ele alacağız. Bir veri listesi bileşeninin durumunu iki istemci isteği arasında korumak için iki yöntem arasında tereddüt edilebilir:

  • [VIEWSTATE] özniteliğini "true" olarak ayarlamak
  • [VIEWSTATE] özniteliğini "false" olarak ayarlamak ve bir sonraki istek sırasında bileşeni bu kaynağa bağlayabilmek için veri kaynağını oturumda saklamak.

Aşağıdaki örnek, veri kapsayıcılarının [VIEWSTATE] mekanizmasının bazı yönlerini göstermektedir. Müşterinin ilk isteğinde, uygulama aşağıdaki görünümü sunar:

no
ad
tür
özellikler
rol
1
DataGrid1
DataGrid
EnableViewState=true
bir S veri kaynağını görüntüler
2
DataGrid2
DataGrid
EnableViewState=true
[DataGrid1] ile aynı S kaynağını görüntüler
3
Button1
Düğme
EnableViewState=false
[submit] düğmesi

[DataGrid1] bileşeni, [VIEWSTATE] mekanizması tarafından yönetilir. Her istekte [DataGrid1]'in görüntüsünü yeniden oluşturan bu mekanizmanın, veri kaynağını da yeniden oluşturup oluşturmadığını araştırıyoruz. Bunun için veri kaynağı, [DataGrid2] bileşenine bağlanmıştır. Bu bileşenin her istekte oluşturulması, [DataGrid1] veri kaynağına açık bir bağlantı aracılığıyla gerçekleştirilir. Ayrıca, [EnableViewState] özniteliği de [vrai]'e aittir.

Uygulamanın [main.aspx] sunum kodu şöyledir:


<%@ page src="main.aspx.vb" inherits="main" autoeventwireup="false" %>
<HTML>
    <HEAD>
        <title></title>
    </HEAD>
    <body>
        <form runat="server">
            <table>
                <tr>
                    <td align="center">DataGrid 1</td>
                    <td align="center">
                        DataGrid 2</td>
                </tr>
                <tr>
                    <td>
                      <asp:DataGrid id="DataGrid1" runat="server" ...>
                            <SelectedItemStyle ...></SelectedItemStyle>
....
                        </asp:DataGrid></td>
                    <td>
                      <asp:DataGrid id="Datagrid2" runat="server" ...>
....
                        </asp:DataGrid></td>
                </tr>
            </table>
            <asp:Button id="Button1" runat="server" Text="Envoyer"></asp:Button>
        </form>
    </body>
</HTML>

[main.aspx.vb] denetleyicisi ise şöyledir:


Imports System.Data

Public Class main
    Inherits System.Web.UI.Page

    Protected WithEvents DataGrid1 As System.Web.UI.WebControls.DataGrid
    Protected WithEvents Datagrid2 As System.Web.UI.WebControls.DataGrid
    Protected WithEvents Button1 As System.Web.UI.WebControls.Button

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' İlk sorguda veri kaynağı tanımlanır ve ilk veri tablosuna bağlanır
        If Not IsPostBack Then
            'veri kaynağını tanımla
            With DataGrid1
                .DataSource = createDataSource()
                .DataBind()
            End With
        End If
        ' her sorguda, datagrid2'yi ilk datagrid'in kaynağıyla bağlar
        With Datagrid2
            .DataSource = DataGrid1.DataSource
            .DataBind()
        End With
    End Sub

    Private Function createDataSource() As DataTable
        ' veri kaynağı başlatılır
        Dim thèmes As New DataTable
        ' sütunlar
        With thèmes.Columns
            .Add("id", GetType(System.Int32))
            .Add("thème", GetType(System.String))
            .Add("description", GetType(System.String))
        End With
        ' id sütunu birincil anahtar olacaktır
        thèmes.Constraints.Add("cléprimaire", thèmes.Columns("id"), True)
        ' satırlar
        Dim ligne As DataRow
        For i As Integer = 0 To 4
            ligne = thèmes.NewRow
            ligne.Item("id") = i.ToString
            ligne.Item("thème") = "thème" + i.ToString
            ligne.Item("description") = "description du thème " + i.ToString
            thèmes.Rows.Add(ligne)
        Next
        Return thèmes
    End Function

    Private Sub InitializeComponent()

    End Sub
End Class

[createDataSource] yöntemi, [DataTable] türünde bir S kaynağı oluşturur. Bu kod, örneğimizin konusu olmadığı için üzerinde durmayacağız. Bizi ilgilendiren, iki [DataGrid] bileşenini oluşturmak için kullanılan yöntemdir:

  • [DataGrid1] bileşeni, ilk sorgu sırasında S tablosuna bir kez bağlanır. Daha sonra bu bağlantı kesilir.
  • [DataGrid2] bileşeni, her yeni sorguda [DataGrid1.DataSource] kaynağına bağlanır.

İlk sorguda şu görünüm elde edilir:

Image

Mantıklı bir şekilde, her iki bileşen de kendilerine bağlandıkları veri kaynağını görüntüler. [Envoyer] düğmesini kullanarak sunucuya bir [PostBack] isteği göndeririz. Elde ettiğimiz görünüm şöyledir:

Image

[DataGrid1] bileşeninin değerini koruduğunu, ancak [DataGrid2] bileşeninin değerini korumadığını görüyoruz. Açıklama:

  • [Page_Load] prosedürü başlamadan önce bile, [DataGrid1] ve [DataGrid2] nesneleri, [viewstate] mekanizması nedeniyle önceki sorguda sahip oldukları değeri geri almışlardır. Nitekim her ikisinin de [EnableViewState] özelliği, [vrai] olarak ayarlanmıştır.
  • [Page_Load] prosedürü yürütülür. Burada bir [PostBack] işlemiyle karşı karşıya olduğumuzdan, [DataGrid1] bileşeni [Page_Load] tarafından değiştirilmez (koduna bakınız). Bu nedenle, [viewstate] sayesinde alınan değeri korur. Yukarıdaki ekran görüntüsü bunu göstermektedir.
  • [DataGrid2] bileşeni ise [DataBind] aracılığıyla [DataGrid1.DataSource] veri kaynağına bağlıdır. Dolayısıyla yeniden oluşturulur ve [viewstate] sayesinde az önce aldığı değer kaybolur. Bu durumda, durumunun gereksiz yere yönetilmesini önlemek için bu bileşenin [EnableViewState] özelliğinin [faux]'e ayarlanması daha uygun olurdu. Yukarıdaki ekran görüntüsü, [DataGrid2]'in boş bir kaynağa bağlandığını göstermektedir. Bu kaynak [DataGrid1.DataSource] olduğundan, bundan şu sonuç çıkarılabilir: [viewstate] mekanizması, [DataGrid1] bileşeninin görüntüsünü düzgün bir şekilde geri yüklesede, [DataSource] gibi özelliklerini geri yüklemez.

Bu örnekten ne sonuç çıkarılabilir? Bir veri konteynerinin [EnableViewState] özelliğini [vrai] olarak ayarlamaktan kaçınılmalıdır; çünkü bu konteyner her sorguda bir veri kaynağına (DataBind) bağlanmalıdır. Ancak, bu durumda bile veri konteynerinin [EnableViewState] özelliğinin [vrai] olarak tutulması gereken bazı durumlar vardır; aksi takdirde yönetilmek istenen olaylar tetiklenmez. Bununla ilgili bir örnekle karşılaşacağız.

Çoğu zaman, bir veri konteynerinin veri kaynağı istekler ilerledikçe değişir. Bu nedenle, her istekte konteyneri veri kaynağına bağlamak gerekir. İsteklerin bu kaynağa erişebilmesi için kaynağın oturumda tutulması yaygın bir uygulamadır. İkinci örneğimiz bu mekanizmayı göstermektedir. Uygulama yalnızca tek bir görünüm sunar:

No.
ad
tür
özellikler
rol
1
DataGrid1
DataGrid
EnableViewState=true
bir S veri kaynağını görüntüler
2
DataGrid2
DataGrid
EnableViewState=false
[DataGrid1] ile aynı S kaynağını görüntüler
3
Button1
Düğme
EnableViewState=false
düğme [submit]
4
lblInfo1
lblInfo2
lblInfo3
Etiket
EnableViewState=false
bilgilendirici metinler

[DataGrid1] bileşeni, yalnızca ilk sorguda verilerle ilişkilendirilir. [viewstate] mekanizması sayesinde, sonraki sorgularda da değerini korur. [DataGrid2] bileşeni, her yeni istekte bir öğe eklenen bir veri kaynağına her istekte bağlanır. Bu nedenle, [DataGrid2] bileşenini her isteğe (DataBind) bağlamak gerekir. Bu nedenle, daha önce önerildiği gibi, [EnableViewState] özniteliğini [faux] olarak ayarladık. Böylece, ikinci sorguda ([Envoyer] düğmesinin kullanılmasıyla), şu yanıtı alıyoruz:

Image

[DataGrid1] bileşeni başlangıç değerini korumuştur. [DataGrid2] bileşeninde bir öğe daha bulunmaktadır. [1,2,2]'teki üç bilgi, istek numarasını temsil etmektedir. Bu bilgilerden birinin hatalı olduğu görülüyor. Bunun nedenini anlamaya çalışacağız.

Uygulamanın [main.aspx] sunum kodu şu şekildedir:


<%@ Page src="main.aspx.vb" inherits="main" autoeventwireup="false" Language="vb" %>
<HTML>
    <HEAD>
        <title></title>
    </HEAD>
    <body>
        <form runat="server">
            <table>
                <tr>
                    <td align="center" bgColor="#ccffcc">DataGrid 1</td>
                    <td align="center" bgColor="#ffff99">DataGrid 2</td>
                </tr>
                <tr>
                    <td vAlign="top">
                        <asp:DataGrid id="DataGrid1" runat="server" ...>
...
                        </asp:DataGrid>
                    </td>
                    <td vAlign="top">
                        <asp:DataGrid id="Datagrid2" runat="server" ... EnableViewState="False">
....
                        </asp:DataGrid>
                    </td>
                </tr>
            </table>
            <P>Numéro de requête&nbsp;:
                <asp:Label id="lblInfo1" runat="server" EnableViewState="False"></asp:Label>,
                <asp:Label id="lblInfo2" runat="server" EnableViewState="False"></asp:Label>,
                <asp:Label id="lblInfo3" runat="server" EnableViewState="False"></asp:Label></P>
            <P>
                <asp:Button id="Button1" runat="server" Text="Envoyer" EnableViewState="False"></asp:Button></P>
        </form>
    </body>
</HTML>

[main.aspx.vb] denetleyicisinin kodu şöyledir:


Imports System.Data
Imports System

Public Class main
    Inherits System.Web.UI.Page

    Protected WithEvents DataGrid1 As System.Web.UI.WebControls.DataGrid
    Protected WithEvents Datagrid2 As System.Web.UI.WebControls.DataGrid
    Protected WithEvents Button1 As System.Web.UI.WebControls.Button
    Protected WithEvents lblInfo1 As System.Web.UI.WebControls.Label
    Protected WithEvents lblInfo2 As System.Web.UI.WebControls.Label
    Protected WithEvents lblInfo3 As System.Web.UI.WebControls.Label

    Dim dtThèmes As DataTable
    Dim numRequête1 As Integer
    Dim numRequête2 As Integer
    Dim numRequête3 As New entier

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' İlk sorguda veri kaynağı tanımlanır ve 1. veri tablosuna bağlanır
        If Not IsPostBack Then
            'veri kaynağını tanımla
            dtThèmes = createDataSource()
            With DataGrid1
                .DataSource = dtThèmes
                .DataBind()
            End With
            ' bilgileri oturumda saklayın
            Session("source") = dtThèmes
            numRequête1 = 0 : Session("numRequête1") = numRequête1
            numRequête2 = 0 : Session("numRequête2") = numRequête2
            numRequête3.valeur = 0 : Session("numRequête3") = numRequête3
        End If
        ' her sorguda yeni bir tema eklenir
        dtThèmes = CType(Session("source"), DataTable)
        Dim nbThèmes = dtThèmes.Rows.Count
        Dim ligne As DataRow = dtThèmes.NewRow
        With ligne
            .Item("id") = nbThèmes.ToString
            .Item("thème") = "thème" + nbThèmes.ToString
            .Item("description") = "description du thème " + nbThèmes.ToString
        End With
        dtThèmes.Rows.Add(ligne)
        'veri tablosu 2'yi veri kaynağıyla ilişkilendir
        With Datagrid2
            .DataSource = dtThèmes
            .DataBind()
        End With
        ' istek sayısı bilgileri
        numRequête1 = CType(Session("numRequête1"), Integer)
        numRequête1 += 1
        lblInfo1.Text = numRequête1.ToString
        numRequête2 = CType(Session("numRequête2"), Integer)
        numRequête2 += 1
        lblInfo2.Text = numRequête2.ToString
        numRequête3 = CType(Session("numRequête3"), entier)
        numRequête3.valeur += 1
        lblInfo3.Text = numRequête3.valeur.ToString
        ' oturumda bazı bilgiler saklanır
        Session("numRequête2") = numRequête2
    End Sub

    Private Function createDataSource() As DataTable
....
    End Function
End Class

Public Class entier
    Private _valeur As Integer
    Public Property valeur() As Integer
        Get
            Return _valeur
        End Get
        Set(ByVal Value As Integer)
            _valeur = Value
        End Set
    End Property
End Class

[createDataSource] yönteminin kodunu buraya aktarmadık. Bu kod, önceki uygulamadakiyle aynıdır; tek fark, kaynak kodda sadece üç satır yer almasıdır. Öncelikle veri kaynağının ve iki konteynerin yönetimine bakalım:


    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' İlk istekte veri kaynağı tanımlanır ve ilk datagrid'e bağlanır
        If Not IsPostBack Then
            'veri kaynağını tanımla
            dtThèmes = createDataSource()
            With DataGrid1
                .DataSource = dtThèmes
                .DataBind()
            End With
            ' bilgileri oturumda saklama
            Session("source") = dtThèmes
...
        End If
        ' her istekte yeni bir tema eklenir
        dtThèmes = CType(Session("source"), DataTable)
        Dim nbThèmes = dtThèmes.Rows.Count
        Dim ligne As DataRow = dtThèmes.NewRow
        With ligne
            .Item("id") = nbThèmes.ToString
            .Item("thème") = "thème" + nbThèmes.ToString
            .Item("description") = "description du thème " + nbThèmes.ToString
        End With
        dtThèmes.Rows.Add(ligne)
        'veri tablosu 2'yi veri kaynağıyla ilişkilendir
        With Datagrid2
            .DataSource = dtThèmes
            .DataBind()
        End With
...
    End Sub

[DataGrid1] bileşeni, yalnızca ilk sorguda S veri kaynağına bağlanır (IsPostBack değil). Bu bileşen daha sonra oturuma yerleştirilir. Daha sonraki sorgularda oturuma yerleştirilmez. Oturuma yerleştirilen S veri kaynağı her sorguda alınır ve ona yeni bir satır eklenir. [DataGrid2] bileşeni ise her sorguda S veri kaynağına açıkça bağlanır. Bu nedenle içeriği her sorguda bir satır artar. S veri kaynağının içeriği değiştirildikten sonra, bu kaynağın bir işlemle oturuma açıkça yeniden eklenmediği görülür:

            Session("source") = S

Neden? Bir istek başladığında, oturumun içinde [DataTable] türünde bir Session("source") nesnesi bulunur; bu nesne, son istek sırasındaki haliyle veri kaynağını temsil eder. Bu Session("source") nesnesine S diyelim. Şu kodunu yazdığımızda:


        dtThèmes = CType(Session("source"), DataTable)

[dtThèmes] ve [S], aynı [DataTable] nesnesine ait iki referanstır. Dolayısıyla, [Page_Load] kodunda [dtThèmes] tarafından referans verilen tabloya bir öğe eklendiğinde, bu öğe aynı anda [S] tarafından referans verilen tabloya da eklenir. Sayfanın yürütülmesi tamamlandığında, oturumda bulunan tüm nesneler kaydedilecektir; dolayısıyla Session("source") nesnesi, c.a.d. S, c.a.d ve [dtThèmes] nesneleri de kaydedilecektir. Dolayısıyla, veri kaynağının yeni içeriği kaydedilmiş olur. Aşağıdaki kodun yazılmasına gerek kalmamıştır:

            Session("source") = dtThèmes

Bu kaydı yapmak için, çünkü Session("source") zaten [dtThèmes] değerine eşittir. Oturuma aktarılan veriler, [Integer, Float, ...] yapıları gibi nesneler olmadığında bu durum geçerli değildir. İstek sayaçlarının yönetimi de bunu göstermektedir:


    Dim numRequête1 As Integer
    Dim numRequête2 As Integer
    Dim numRequête3 As New entier

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' İlk istekte veri kaynağı tanımlanır ve ilk datagrid'e bağlanır
....
            ' bilgileri oturumda saklamak
            Session("source") = dtThèmes
            numRequête1 = 0 : Session("numRequête1") = numRequête1
            numRequête2 = 0 : Session("numRequête2") = numRequête2
            numRequête3.valeur = 0 : Session("numRequête3") = numRequête3
        End If
        ' her sorguda yeni bir tema eklenir
....
        ' istek sayısı bilgileri
        numRequête1 = CType(Session("numRequête1"), Integer)
        numRequête1 += 1
        lblInfo1.Text = numRequête1.ToString
        numRequête2 = CType(Session("numRequête2"), Integer)
        numRequête2 += 1
        lblInfo2.Text = numRequête2.ToString
        numRequête3 = CType(Session("numRequête3"), entier)
        numRequête3.valeur += 1
        lblInfo3.Text = numRequête3.valeur.ToString
        ' oturumda bazı bilgiler saklanır
        Session("numRequête2") = numRequête2
    End Sub

    Private Function createDataSource() As DataTable
....
    End Function

    Private Sub InitializeComponent()

    End Sub
End Class

Public Class entier
    Private _valeur As Integer
    Public Property valeur() As Integer
        Get
            Return _valeur
        End Get
        Set(ByVal Value As Integer)
            _valeur = Value
        End Set
    End Property

İstek sayaçları üç öğede saklanır:

  • numRequête1 ve numRequête2 ([Integer] türünde) - [Integer] bir sınıf değil, bir yapıdır
  • numRequête3, [entier] türündedir - [entier] ise bu amaçla tanımlanmış bir sınıftır

Şu kod yazıldığında:


        numRequête1 = CType(Session("numRequête1"), Integer)
..
        numRequête2 = CType(Session("numRequête2"), Integer)
..
        numRequête3 = CType(Session("numRequête3"), entier)
..
  • [Session("numRequête1")] yapısı, [numRequête1]'e kopyalanır. Dolayısıyla, [numRequête1] öğesi değiştirildiğinde, [Session("numRequête1")] öğesi değiştirilmez
  • Aynı durum [Session("numRequête2")] ve [numRequête2] için de geçerlidir
  • [Session("numRequête3")] ve [numRequête3] öğeleri ise, her ikisi de [entier] türündeki aynı nesneye referans vermektedir. Referans verilen nesne, bu referanslardan herhangi biri aracılığıyla değiştirilebilir.

Bundan, şunu yazmanın gereksiz olduğu sonucuna varılır:

        Session("numRequête3") = numRequête3

yazmanın gereksiz olduğu sonucuna varılır. Bunun yerine şunu yazmak gerekir:

        Session("numRequête1") = numRequête1
        Session("numRequête2") = numRequête2

yazmak gerekir. Bunu yalnızca [numRequête2] için yapıyoruz; bu da ikinci sorgunun sonucunda elde edilen ekran görüntüsünde [numRequête1] sayacının hatalı olmasının nedenini açıklıyor.

Dolayısıyla şunu unutmamak gerekir: Bir veri, oturuma bir kez eklendikten sonra, bir nesne ile temsil ediliyorsa tekrar tekrar eklenmesine gerek yoktur. Diğer durumlarda ise, veri değiştirilmişse bu işlem yapılmalıdır.

8.6. Sayfalandırılmış ve sıralanmış bir DataGrid kullanarak veri listesinin görüntülenmesi

[DataGrid] bileşeni, bir [DataSet]'in içeriğini görüntülemeye olanak tanır. Şu ana kadar [DataSet]'lerimizi her zaman "elle" oluşturduk. Bu sefer, bir veritabanından alınan bir [DataSet] kullanıyoruz. Aşağıdaki MVC uygulamasını oluşturuyoruz:

Üç görünüm, [main.aspx] denetleyicisinin sunum koduna konteynerler şeklinde eklenecek. Dolayısıyla bu uygulamanın tek bir sayfası var: [main.aspx].

8.6.1. İşlev sınıfları

[produits] sınıfı, aşağıdaki ACCESS veritabanına erişim sağlar:

Image

[produits] sınıfının kodu şöyledir:


Imports System
Imports System.Data
Imports System.Data.OleDb
Imports System.Xml

Namespace st.istia.univangers.fr

    Public Class produits
        Private chaineConnexionOLEDB As String

        Public Sub New(ByVal chaineConnexionOLEDB As String)
            ' bağlantı dizesi saklanır
            Me.chaineConnexionOLEDB = chaineConnexionOLEDB
        End Sub

        Public Function getDataSet(ByVal commande As String) As DataSet
            ' DataAdapter nesnesi oluşturulur ve OLEDB kaynağındaki veriler okunur
            Dim adaptateur As New OleDbDataAdapter(commande, chaineConnexionOLEDB)
            ' SELECT sorgusunun sonucunun bellekteki görüntüsü oluşturulur
            Dim contenu As New DataSet
            Try
                adaptateur.Fill(contenu)
            Catch e As Exception
                Throw New Exception("Erreur d'accès à la base de données (" + e.Message + ")")
            End Try
            ' sonuç döndürülür
            Return contenu
        End Function
    End Class
End Namespace

ACCESS veritabanı, OLEDB sürücüsü aracılığıyla yönetilecektir. [produits] sınıfının oluşturucusuna, kimlik bilgilerini içeren bağlantı dizesi, OLEDB sürücüsü ve yönetilmesi gereken veritabanı verilir. [produits] sınıfı,metodunun içinde metin parametre olarak geçirilir. Metodun işleyişi sırasında birkaç işlem gerçekleşir: veritabanına bağlantı kurulması, [select]'in çalıştırılması, bağlantının kapatılması. Tüm bunlar bir istisna oluşturabilir ve bu istisna burada yönetilir. Bir test programı şu şekilde olabilir:

Option Explicit On 
Option Strict On

' ad alanları
Imports System
Imports System.Data
Imports Microsoft.VisualBasic

Namespace st.istia.univangers.fr

     ' test sayfası
    Module testproduits
        Sub Main(ByVal arguments() As String)
             ' ürün tablosunun içeriğini görüntüler
             ' tablo, pg'nin dosya adını aldığı ACCESS veritabanında bulunuyor
            Const syntaxe1 As String = "pg bdACCESS"

             ' program parametrelerinin doğrulanması
            If arguments.Length <> 1 Then
                 ' hata mesajı
                Console.Error.WriteLine(syntaxe1)
                 ' son
                Environment.Exit(1)
            End If

             ' bağlantı dizesi hazırlanıyor
            Dim chaineConnexion As String = "Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4; Data Source=" + arguments(0)

             ' ürün nesnesinin oluşturulması
            Dim objProduits As produits = New produits(chaineConnexion)

             ' ürün tablosu bir veri kümesine alınıyor
            Dim contenu As DataSet
            Try
                contenu = objProduits.getDataSet("select id,nom,prix from liste")
            Catch ex As Exception
                Console.Error.WriteLine(("L'erreur suivante s'est produite : " + ex.Message))
                Environment.Exit(2)
            End Try

             ' içeriği görüntüleniyor
            Dim lignes As DataRowCollection = contenu.Tables(0).Rows
            For i As Integer = 0 To lignes.Count - 1
                 ' tablonun i. satırı
                Console.Out.WriteLine(lignes(i).Item("id").ToString + "," + lignes(i).Item("nom").ToString + _
                "," + lignes(i).Item("prix").ToString)
            Next
        End Sub
    End Module
End Namespace

Bu uygulamanın çeşitli öğelerinin derlenmesi şu şekilde gerçekleştirilir:

dos>vbc /t:library /r:system.dll /r:system.data.dll /r:system.xml.dll produits.vb

dos>vbc /r:produits.dll /r:system.data.dll /r:system.xml.dll /r:system.dll testproduits.vb

dos>dir
06/05/2004  16:52              118 784 produits.mdb
07/05/2004  11:07                  902 produits.vb
07/04/2004  07:01                1 532 testproduits.vb
07/05/2004  14:21                3 584 produits.dll
07/05/2004  14:22                4 608 testproduits.exe

dos>testproduits produits.mdb
1,produit1,10
2,produit2,20
3,produit3,30

8.6.2. Görünümler

Artık veri erişim sınıfımız olduğuna göre, bu web uygulamasının denetleyicilerini ve görünümlerini yazacağız. Öncelikle nasıl çalıştığına bir göz atalım. İlk görünüm şöyledir:

no
ad
tür
özellikler
rol
1
txtSelect
TextBox
EnableViewState=true
select sorgusu giriş alanı
2
RequiredFieldValidator1
RequiredFieldValidator
EnableViewState=false
1'in varlığını kontrol eder
3
txtPages
TextBox
EnableViewState=true
giriş alanı - sonuç sayfası başına görüntülenecek veri satır sayısını belirtir
4
RequiredFieldValidator2
RequiredFieldValidator
EnableViewState=false
3'ün varlığını kontrol eder
5
RangeValidator1
RangeValidator
EnableViewState=false
(3) değerinin [1,30] aralığında olup olmadığını kontrol eder
6
btnExécuter
Düğme
EnableViewState=false
[submit] düğmesi

Bu görünüme [formulaire] adı vereceğiz. Bu görünüm, kullanıcının [produits.mdb] veritabanında bir SQL select sorgusu çalıştırmasına olanak tanır. Sorgunun çalıştırılması, yeni bir görünüm oluşturur:

no
ad
tür
özellikler
rol
1
lblSelect
Etiket
EnableViewState=false
bilgi alanı
2
rdCroissant
rdDécroissant
RadioButton
EnableViewState=false
GroupName=rdTri
sıralama yönünü seçmenizi sağlar
3
DataGrid1
DataGrid
EnableViewState=true
AllowPaging=true
AllowSorting=true
select sonucunu gösteren tablo
4
lnkRésultats
LinkButton
EnableViewState=false
[submit] düğme bağlantısı

Bu görünüme [résultats] adı vereceğiz. [DataGrid] öğesini içeren bu görünüm, SQL select komutunun sonucunu görüntüleyecektir. Kullanıcı sorgusunda hata yapabilir. Doğrulama denetimleri sayesinde, bazı hatalar [erreurs] görünümünde kullanıcıya bildirilecektir.

Image

Diğer hatalar ise [erreurs] görünümü aracılığıyla kullanıcıya bildirilecektir:

Image

[erreurs] görünümü görüntülenir:

no
ad
tür
özellikler
rol
1
erreursHTML
değişken
 
hataların görüntülenmesi için gerekli olan HTML kodu
3
lnkForm2
LinkButton
EnableViewState=false
[submit] bağlantı düğmesi

Uygulamanın üç görünümü, aynı sayfa içindeki üç farklı panel (konteyner)dir: [main.aspx]. Sunum kodu şu şekildedir:


<%@ Page src="main.aspx.vb" inherits="main" autoeventwireup="false" Language="vb" %>
<HTML>
    <HEAD>
    </HEAD>
    <body>
        <P>Liaison de données avec un DataGrid</P>
        <HR width="100%" SIZE="1">
        <form runat="server">
            <asp:panel id="vueFormulaire" runat="server">
                <P>Commande [select] à exécuter sur la table LISTE</P>
                <P>&nbsp;Exemple : select id, nom, prix from LISTE
                </P>
                <P>
                    <asp:TextBox id="txtSelect" runat="server" Columns="60"></asp:TextBox></P>
                <P>
                    <asp:RequiredFieldValidator id="RequiredFieldValidator1" runat="server" EnableViewState="False" EnableClientScript="False"
                        ErrorMessage="Indiquez la requête [select] à exécuter" ControlToValidate="txtSelect" Display="Dynamic"></asp:RequiredFieldValidator></P>
                <P>Nombre de lignes par page :
                    <asp:TextBox id="txtPages" runat="server" Columns="3"></asp:TextBox></P>
                <P>
                    <asp:RequiredFieldValidator id="RequiredFieldValidator2" runat="server" EnableViewState="False" EnableClientScript="False"
                        ErrorMessage="Indiquez le nombre de lignes par page désirées" ControlToValidate="txtPages" Display="Dynamic"></asp:RequiredFieldValidator>
                    <asp:RangeValidator id="RangeValidator1" runat="server" EnableViewState="False" EnableClientScript="False"
                        ErrorMessage="Vous devez indiquer un nombre entre 1 et 30" ControlToValidate="txtPages" Display="Dynamic"
                        Type="Integer" MinimumValue="1" MaximumValue="30"></asp:RangeValidator></P>
                <P>
                    <asp:Button id="btnExécuter" runat="server" EnableViewState="False" Text="Exécuter"></asp:Button></P>
            </asp:panel>
            <asp:Panel id="vueRésultats" runat="server">
                <P>Résultats de la requête
                    <asp:Label id="lblSelect" runat="server"></asp:Label></P>
                <P>Tri
                    <asp:RadioButton id="rdCroissant" runat="server" Text="croissant" Checked="True" GroupName="rdTri"></asp:RadioButton>
                    <asp:RadioButton id="rdDécroissant" runat="server" Text="décroissant" GroupName="rdTri"></asp:RadioButton></P>
                <P>
                    <asp:DataGrid id="DataGrid1" runat="server" BorderColor="#CC9966" BorderStyle="None" BorderWidth="1px"
                        BackColor="White" CellPadding="4" AllowPaging="True" PageSize="4" AllowSorting="True">
                        <SelectedItemStyle Font-Bold="True" ForeColor="#663399" BackColor="#FFCC66"></SelectedItemStyle>
                        <ItemStyle ForeColor="#330099" BackColor="White"></ItemStyle>
                        <HeaderStyle Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle>
                        <FooterStyle ForeColor="#330099" BackColor="#FFFFCC"></FooterStyle>
                        <PagerStyle NextPageText="Suivant" PrevPageText="Pr&#233;c&#233;dent" HorizontalAlign="Center"
                            ForeColor="#330099" BackColor="#FFFFCC"></PagerStyle>
                    </asp:DataGrid></P>
                <P>
                    <asp:LinkButton id="lnkRésultats" runat="server" EnableViewState="False">Retour au formulaire</asp:LinkButton></P>
            </asp:Panel>
            <asp:Panel id="vueErreurs" runat="server">
                <P>Les erreurs suivantes se sont produites :</P>
                <% =erreursHTML %>
                <P>
                    <asp:LinkButton id="lnkErreurs" runat="server" EnableViewState="False">Retour vers le formulaire</asp:LinkButton></P>
            </asp:Panel>
        </form>
    </body>
</HTML>

8.6.3. DataGrid'in yapılandırılması

İlk kez karşılaştığımız [DataGrid] bileşeninin sayfalandırma özelliğine biraz daha yakından bakalım. Yukarıdaki kodda, bu sayfalandırma aşağıdaki özniteliklerle kontrol edilmektedir:


                    <asp:DataGrid id="DataGrid1" runat="server" PageSize="4" AllowPaging="True" ...>
...
                        <PagerStyle NextPageText="Suivant" PrevPageText="Pr&#233;c&#233;dent" ...></PagerStyle>
                    </asp:DataGrid></P>
AllowPaging="true"
sayfa numaralandırmasına izin ver
PageSize="4"
sayfa başına dört satır veri
NextPageText="Suivant"
Veri kaynağının bir sonraki sayfasına gitmek için bağlantı metni
PrevPageText="Précédent"
Veri kaynağının bir önceki sayfasına gitmek için kullanılan bağlantı metni

Bu bilgiler doğrudan <asp:datagrid> etiketinin özniteliklerine girilebilir. Ayrıca [WebMatrix]'ten de yararlanılabilir. [DataGrid]'in özellikler penceresinde, [Générateur de propriétés] bağlantısını takip edin:

Image

Aşağıdaki sihirbaz açılır:

Image

[Pagination] seçeneğini seçin:

Image

Yukarıda, sunum kodundaki [DataGrid]'in sayfalandırma özniteliklerinin değerlerini görüyoruz.

Ayrıca, [DataGrid]'in sütunlarından birine göre verilerin sıralanmasına izin veriyoruz. Bunu yapmanın çeşitli yolları vardır. Bunlardan biri, [DataGrid]'in özellikler penceresinde [AllowSorting=true] özelliğini tanımlamaktır. Özellik oluşturucu da kullanılabilir. Hangi yöntem kullanılırsa kullanılsın, sonuç olarak bileşenin <asp:DataGrid> etiketinde [AllowSorting=true] özniteliği bulunur:


                    <asp:DataGrid id="DataGrid1" runat="server" ... AllowPaging="True" PageSize="4" AllowSorting="True">

8.6.4. Denetleyiciler

[global.asax, global.asax.vb] denetleyicisi şu şekildedir:

[global.asax]

<%@ Application src="global.asax.vb" inherits="Global" %>

[global.asax.vb]


Imports st.istia.univangers.fr
Imports System.Configuration

Public Class Global
    Inherits System.Web.HttpApplication

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' bir ürün nesnesi oluşturulur
        Dim objProduits As produits
        Try
            objProduits = New produits(ConfigurationSettings.AppSettings("OLEDBStringConnection"))
            ' nesneyi uygulamaya eklenir
            Application("objProduits") = objProduits
            ' hata yok
            Application("erreur") = False
        Catch ex As Exception
            'hata oluştu, uygulamaya kaydediliyor
            Application("erreur") = True
            Application("message") = ex.Message
        End Try
    End Sub
End Class

Uygulama başlatıldığında (Application_Start), bir [produits] nesnesi oluşturur ve tüm istemcilerin tüm istekleri için kullanılabilir olması amacıyla bunu uygulamaya yerleştiririz. Bu oluşturma işlemi sırasında bir istisna meydana gelirse, bu durum uygulamada kaydedilir. [Application_Start] prosedürü yalnızca bir kez çalıştırılacaktır. Bundan sonra [global.asax] denetleyicisi devreye girmeyecektir. Bu noktada işi [main.aspx.vb] denetleyicisi üstlenecektir:


Imports System.Collections
Imports Microsoft.VisualBasic
Imports System.Data
Imports st.istia.univangers.fr
Imports System
Imports System.Xml

Public Class main
    Inherits System.Web.UI.Page

    ' sayfa bileşenleri
    Protected WithEvents txtSelect As System.Web.UI.WebControls.TextBox
    Protected WithEvents RequiredFieldValidator1 As System.Web.UI.WebControls.RequiredFieldValidator
    Protected WithEvents txtPages As System.Web.UI.WebControls.TextBox
    Protected WithEvents RequiredFieldValidator2 As System.Web.UI.WebControls.RequiredFieldValidator
    Protected WithEvents RangeValidator1 As System.Web.UI.WebControls.RangeValidator
    Protected WithEvents btnExécuter As System.Web.UI.WebControls.Button
    Protected WithEvents vueFormulaire As System.Web.UI.WebControls.Panel
    Protected WithEvents lblSelect As System.Web.UI.WebControls.Label
    Protected WithEvents DataGrid1 As System.Web.UI.WebControls.DataGrid
    Protected WithEvents lnkRésultats As System.Web.UI.WebControls.LinkButton
    Protected WithEvents vueRésultats As System.Web.UI.WebControls.Panel
    Protected WithEvents lnkErreurs As System.Web.UI.WebControls.LinkButton
    Protected WithEvents vueErreurs As System.Web.UI.WebControls.Panel
    Protected WithEvents rdCroissant As System.Web.UI.WebControls.RadioButton
    Protected WithEvents rdDécroissant As System.Web.UI.WebControls.RadioButton
    ' sayfa verileri
    Protected erreursHTML As String

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' uygulamada hata olup olmadığına bakılıyor
        If CType(Application("erreur"), Boolean) Then
            ' uygulama düzgün bir şekilde başlatılamadı
            Dim erreurs As New ArrayList
            erreurs.Add("Application momentanément indisponible (" + CType(Application("message"), String) + ")")
            afficheErreurs(erreurs, False)
            Exit Sub
        End If
        '1. istek
        If Not IsPostBack Then
            ' boş form görüntüleniyor
            afficheFormulaire()
        End If
    End Sub

    Private Sub afficheErreurs(ByVal erreurs As ArrayList, ByVal afficheLien As Boolean)
        ' hata görünümünü görüntüler
        erreursHTML = ""
        For i As Integer = 0 To erreurs.Count - 1
            erreursHTML += "<li>" + erreurs(i).ToString + "</li>" + ControlChars.CrLf
        Next
        lnkErreurs.Visible = afficheLien
        ' [erreurs] görünümü görüntüleniyor
        vueErreurs.Visible = True
        vueFormulaire.Visible = False
        vueRésultats.Visible = False
    End Sub

    Private Sub afficheFormulaire()
        ' [formulaire] görünümü görüntülenir
        vueFormulaire.Visible = True
        vueErreurs.Visible = False
        vueRésultats.Visible = False
    End Sub

    Private Sub afficheRésultats(ByVal sqlTexte As String, ByVal données As DataView)
        ' kontroller başlatılıyor
        lblSelect.Text = sqlTexte
        With DataGrid1
            .DataSource = données
            .PageSize = CType(txtPages.Text, Integer)
            .CurrentPageIndex = 0
            .DataBind()
        End With
        ' [résultats] görünümü görüntülenir
        vueRésultats.Visible = True
        vueFormulaire.Visible = False
        vueErreurs.Visible = False
    End Sub

    Private Sub btnExécuter_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExécuter.Click
        ' sayfa geçerli mi?
        If Not Page.IsValid Then
            afficheFormulaire()
            Exit Sub
        End If

        ' SELECT istemci sorgusu yürütülüyor
        Dim données As DataView
        Try
            données = CType(Application("objProduits"), produits).getDataSet(txtSelect.Text.Trim).Tables(0).DefaultView
        Catch ex As Exception
            Dim erreurs As New ArrayList
            erreurs.Add("erreur d'accès à la base de données (" + ex.Message + ")")
            afficheErreurs(erreurs, True)
            Exit Sub
        End Try
        ' her şey yolunda - sonuçlar görüntüleniyor
        afficheRésultats(txtSelect.Text.Trim, données)
        ' veriler oturuma aktarılıyor
        Session("données") = données
    End Sub

    Private Sub retourFormulaire(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lnkErreurs.Click, lnkRésultats.Click
        ' görünüm kümesi
        vueErreurs.Visible = False
        vueFormulaire.Visible = True
        vueRésultats.Visible = False
    End Sub

    Private Sub DataGrid1_PageIndexChanged(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) Handles DataGrid1.PageIndexChanged
        ' sayfa değişimi
        With DataGrid1
            .CurrentPageIndex = e.NewPageIndex
            .DataSource = CType(Session("données"), DataView)
            .DataBind()
        End With
    End Sub

    Private Sub DataGrid1_SortCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) Handles DataGrid1.SortCommand
        ' veri görünümü sıralanıyor
        Dim données As DataView = CType(Session("données"), DataView)
        données.Sort = e.SortExpression + " " + CType(IIf(rdCroissant.Checked, "asc", "desc"), String)
        ' görüntüleniyor
        With DataGrid1
            .CurrentPageIndex = 0
            .DataSource = données
            .DataBind()
        End With
    End Sub
End Class

[Page_Load] sayfası yüklendiğinde, öncelikle uygulamanın düzgün bir şekilde başlatılıp başlatılmadığını kontrol ederiz. Başlatılamamışsa, [erreurs] görünümü, forma geri dönme bağlantısı olmadan görüntülenir; çünkü bu bağlantı bu durumda gereksizdir. Aslında, uygulama düzgün bir şekilde başlatılamamışsa yalnızca [erreurs] görünümü görüntülenebilir. Aksi takdirde, istemciden gelen ilk istek söz konusuysa [formulaire] görünümü görüntülenir. Geri kalan kısım için ise kodu anlamayı okuyucuya bırakıyoruz. Sadece üç prosedür üzerinde duracağız: kullanıcı, [formulaire] görünümüne girilen SQL isteğinin yürütülmesini talep ettiğinde çalıştırılan [btnExécuter_Click] prosedürü, kullanıcı,kullanıcı [DataGrid]'teki [Suivant] ve [Précédent] bağlantılarını kullandığında çalıştırılan [DataGrid1_PageIndexChanged] prosedürü ve kullanıcının verileri sıralama amacıyla bir sütun başlığına tıkladığındasırasına göre sıralamak istediğinde çalıştırılır. Sıralamanın artan veya azalan yönü, iki sıralama radyo düğmesi ile belirlenir.

Dolayısıyla, [btnExécuter_Click] prosedüründe ilk olarak sayfanın geçerli olup olmadığı kontrol edilir. [btnExécuter_Click] prosedürü yürütüldüğünde, sayfanın çeşitli geçerlilik denetimleriyle ilgili kontroller yapılmış olur. Her bir geçerlilik denetimi için iki öznitelik ayarlanmıştır:

IsValid
doğrulanmış veri geçerliyse "true", değilse "false" olarak ayarlanır
ErrorMessage
doğrulanmış verinin geçersiz olduğu tespit edildiğinde hata mesajı

Sayfanın kendisi için ise bir [IsValid] özniteliği ayarlanmıştır. Bu öznitelik, yalnızca tüm doğrulama denetimlerinin [IsValid] özniteliği "true" ise "true" olur. Aksi takdirde, [formulaire] görünümü görüntülenmelidir. Bu görünüm, [errorMessage] özniteliğini görüntüleyecek doğrulama denetimlerini içerir. Sayfa geçerliyse, [Application_Start] tarafından oluşturulan [produits] türündeki nesne kullanılarak, SQL select sorgusunun yürütülmesine karşılık gelen [DataSet] elde edilir. Bunu [DataView] nesnesine dönüştürürüz:


        Dim données As DataView
        Try
            données = CType(Application("objProduits"), produits).getDataSet(txtSelect.Text.Trim).Tables(0).DefaultView
...

[DataSet] ile çalışıp şunu yazabilirdik:


        Dim données As DataSet
        Try
            données = CType(Application("objProduits"), produits).getDataSet(txtSelect.Text.Trim)
...

Bir [DataSet] nesnesi, temelde ilişkilerle birbirine bağlanmış bir dizi tablodan oluşur. Özel uygulamamızda, [produits] sınıfından elde edilen [DataSet], yalnızca [select] komutunun sonucundan elde edilen tek bir tablo içerir. Bir tablo sıralanabilirken bir [DataSet] sıralanamaz; ancak elde edilen verileri sıralamak istiyoruz. [select] komutunun sonuç tablosuyla çalışmak için şunu yazabilirdik:


        Dim données As DataTable
        Try
            données = CType(Application("objProduits"), produits).getDataSet(txtSelect.Text.Trim).Tables(0)
...

[DataTable] nesnesi, bir veritabanı tablosunu temsil etmesine rağmen sıralama yöntemine sahip değildir. Bunun için tablonun bir görünümüne sahip olmak gerekir. Bir görünüm, [DataView] türünde bir nesnedir. Filtreler yardımıyla aynı tablo üzerinde farklı görünümler elde edilebilir. Bir tablonun, üzerinde herhangi bir filtre tanımlanmamış olan varsayılan bir görünümü vardır. Dolayısıyla bu görünüm, tablonun tamamını temsil eder. Bu varsayılan görünüm, [DataTable.DefaultView] ile elde edilir. Bir görünümü, daha sonra ele alacağımız [sort] özelliği kullanılarak sıralayabiliriz.

[produits] sınıfının [DataSet] değeri başarıyla elde edilirse, [résultats] görünümü görüntülenir; aksi takdirde [erreurs] görünümü görüntülenir. [résultats] görünümünün görüntülenmesi, iki parametre aktarılan [afficheRésultats] prosedürü ile gerçekleştirilir:

  • [lblSelect] etiketine yerleştirilecek metin
  • [DataGrid1] ile ilişkilendirilecek [DataView]

Bu örnek, [DataGrid] bileşeninin büyük esnekliğini göstermektedir. Bu bileşen, kendisine bağlanan [DataView]’in yapısını tanıyabilmekte ve buna uyum sağlayabilmektedir. Son olarak, [btnExécuter_Click] prosedürü, kullanıcının oturumunda az önce elde ettiği [DataView]'i, kullanıcı aynı [DataView]'e ait başka sayfalar talep ettiğinde kullanabilmek üzere saklar.

[DataGrid1_PageIndexChanged] prosedürü, kullanıcı [DataGrid]'teki [Suivant] ve [Précédent] bağlantılarını kullandığında çalıştırılır. Bu prosedür iki parametre alır:


    Private Sub DataGrid1_PageIndexChanged(ByVal source As Object, ByVal e As System.Web.UI.WebControls.) Handles DataGrid1.PageIndexChanged
source
olayın kaynak nesnesi – bu durumda, [Suivant] veya [Précédent] bağlantılarından biri
e
olayla ilgili bilgiler. e.NewPageIndex özniteliği, müşterinin talebini karşılamak için görüntülenecek sayfa numarasıdır

Olay işleyicisinin tam kodu şöyledir:


    Private Sub DataGrid1_PageIndexChanged(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridPageChangedEventArgs) Handles DataGrid1.PageIndexChanged
        ' sayfa değişimi
        With DataGrid1
            .CurrentPageIndex = e.NewPageIndex
            .DataSource = CType(Session("données"), DataView)
            .DataBind()
        End With
    End Sub

[DataGrid] bileşeninin, görüntülediği veya görüntüleyeceği sayfanın numarasını belirten [CurrentPageIndex] adlı bir özniteliği vardır. Bu özniteliğe, [e] parametresinin değeri olan [NewPageIndex] atanır. Ardından [DataGrid], [btnExécuter_Click] prosedürü aracılığıyla oturumda saklanan [DataView] ile eşleştirilir.

[DataGrid]'in [EnableViewState=true] özniteliğine ihtiyacı olup olmadığı sorgulanabilir; zira içeriği, sayfanın her yeni çalıştırılışında kod tarafından hesaplanmaktadır. İhtiyacı olmadığı düşünülebilir. Ancak, [DataGrid]'in [EnableViewState=false] özniteliğine sahip olması durumunda, [DataGrid1.PageIndexChanged] olayının hiçbir zaman tetiklenmediği görülür. Bu nedenle [EnableViewState=true] bırakılmıştır. Bunun sonucunda, [DataGrid]'in içeriğinin sayfanın gizli [__VIEWSTATE] alanına yerleştirileceği bilinmektedir. [DataGrid] büyükse, bu durum sayfada önemli bir aşırı yüklenmeye neden olabilir. Bu durum sorun yaratıyorsa, [DataGrid]'in otomatik sayfalandırmasını kullanmadan sayfalandırmayı kendimiz yönetebiliriz.

Kullanıcı, [DataGrid] tarafından görüntülenen sütunlardan birinin başlığına tıklayarak verilerin o sütuna göre sıralanmasını istediğinde, [DataGrid1_SortCommand] prosedürü çalıştırılır. Bu prosedür iki parametre alır:


    Private Sub DataGrid1_SortCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) Handles DataGrid1.SortCommand
source
olayın kaynak nesnesi – burada, [Suivant] veya [Précédent] bağlantılarından biri
e
olayla ilgili bilgiler. [e.SortExpression] özniteliği, sıralama için tıklanan sütunun adıdır

Olay işleyicisinin tam kodu şöyledir:


    Private Sub DataGrid1_SortCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) Handles DataGrid1.SortCommand
        ' veri görünümünü sıralama
        Dim données As DataView = CType(Session("données"), DataView)
        données.Sort = e.SortExpression + " " + CType(IIf(rdCroissant.Checked, "asc", "desc"), String)
        ' görüntüleniyor
        With DataGrid1
            .CurrentPageIndex = 0
            .DataSource = données
            .DataBind()
        End With
    End Sub

Geçerli oturumda [DataGrid] tarafından görüntülenen [DataView] alınır. Bunu buraya yerleştiren [btnExécuter_Click] prosedürüdür. [DataView] bileşeninin, sıralama ifadesinin atandığı bir [Sort] özelliği vardır. Bu ifade, [select ... order by expr1, expr2, ...] sözdizimine uyar; burada her bir [expri] öğesinin ardından, artan sıralama için [asc] anahtar sözcüğü veya azalan sıralama için [desc] anahtar sözcüğü gelebilir. Burada kullanılan [order by] ifadesi, [order by colonne asc/desc]'tir. [e.SortExpression] özelliği, sıralama için tıklanan [DataGrid] sütununun adını verir. [asc/desc] dizesi, [rdTri] grubundaki radyo düğmelerinin değerlerine göre belirlenir. [DataView]'in sıralama ifadesi belirlendikten sonra, [DataGrid] buna eşleştirilir. [DataGrid], ilk sayfasına yerleştirilir.

8.7. DataList bileşeni ve veri bağlantısı

Şimdi [DataList] bileşenine odaklanalım. Bu bileşen, [DataGrid]'e göre daha fazla biçimlendirme olanağı sunar, ancak daha az esnektir. Dolayısıyla, bağlı olduğu veri kaynağına otomatik olarak uyum sağlayamaz. İstenirse, bu uyumlaştırma kod yoluyla yapılmalıdır. Veri kaynağının yapısı önceden biliniyorsa, bu bileşen sunduğu biçimlendirme seçenekleri sayesinde [DataGrid] bileşenine tercih edilebilir.

8.7.1. Uygulama

[DataList] bileşeninin kullanımını örneklemek amacıyla, öncekine benzer bir MVC uygulaması oluşturuyoruz:

Üç görünüm, [main.aspx] denetleyicisinin sunum koduna konteynerler şeklinde eklenecektir. Dolayısıyla bu uygulama, tek bir [main.aspx] sayfasına sahiptir.

8.7.2. İşlev sınıfları

[produits] sınıfı, öncekiyle aynıdır.

8.7.3. Görünümler

Kullanıcı uygulamaya ilk isteğini gönderdiğinde, aşağıdaki [résultats1] görünümünü alır:

no
ad
tür
özellikler
rol
1
RadioButton1
RadioButton2
RadioButton
EnableViewState=false
iki seçenek arasından bir [DataList] stili seçmenizi sağlar
2
btnChanger
Düğme
EnableViewState=false
[submit] düğmesi
3
DataList1
DataList
EnableViewState=true
veri listesi görüntüleme alanı

Kullanıcı 2 numaralı stili seçerse, aşağıdaki [résultats2] görünümünü alır:

no
ad
tür
özellikler
rol
1
DataList2
DataList
EnableViewState=true
veri listesi görüntüleme alanı

[erreurs] görünümü, veri kaynağına erişimde bir sorun olduğunu bildiriyor:

numara
ad
tür
özellikler
rol
1
erreursHTML
değişken
 
hataların görüntülenmesi için gerekli olan HTML kodu

Uygulamanın üç görünümü, aynı [main.aspx] sayfası içindeki üç farklı konteynerdir (panel). Sunum kodu şöyledir:


<%@ Page src="main.aspx.vb" inherits="main" autoeventwireup="false" Language="vb" %>
<HTML>
    <HEAD>
    </HEAD>
    <body>
        <P>Liaison de données avec un DataList</P>
        <HR width="100%" SIZE="1">
        <form runat="server" ID="Form1">
            <asp:Panel Runat="server" ID="bandeau">
                <P>Choisissez votre style :
                    <asp:RadioButton id="RadioButton1" runat="server" EnableViewState="False" Text="1" GroupName="rdstyle"
                        Checked="True"></asp:RadioButton>
                    <asp:RadioButton id="RadioButton2" runat="server" EnableViewState="False" Text="2" GroupName="rdstyle"></asp:RadioButton>
                    <asp:Button id="btnChanger" runat="server" EnableViewState="False" Text="Changer"></asp:Button></P>
                <HR width="100%" SIZE="1">
            </asp:Panel>
            <asp:Panel id="vueRésultats1" runat="server">
                <P>
                    <asp:DataList id="DataList1" runat="server" BorderColor="Tan" BorderWidth="1px" BackColor="LightGoldenrodYellow"
                        CellPadding="2" RepeatDirection="Horizontal" RepeatColumns="4" ForeColor="Black">
                        <SelectedItemStyle ForeColor="GhostWhite" BackColor="DarkSlateBlue"></SelectedItemStyle>
                        <HeaderTemplate>
                            Contenu de la table [liste] de la base [produits]
                        </HeaderTemplate>
                        <AlternatingItemStyle BackColor="PaleGoldenrod"></AlternatingItemStyle>
                        <ItemTemplate>
                            nom :
                            <%# Container.DataItem("ad") %>
                            <br>
                            prix :
                            <%# databinder.eval(Container.DataItem,"fiyat","{0:C}") %>
                            <br>
                        </ItemTemplate>
                        <FooterStyle BackColor="Tan"></FooterStyle>
                        <HeaderStyle Font-Bold="True" BackColor="Tan"></HeaderStyle>
                    </asp:DataList></P>
            </asp:Panel>
            <asp:Panel id="vueRésultats2" runat="server">
                <P>
                    <asp:DataList id="DataList2" runat="server">
                        <HeaderTemplate>
                            Contenu de la table [liste] de la base [produits]
                            <HR width="100%" SIZE="1">
                        </HeaderTemplate>
                        <AlternatingItemStyle BackColor="Teal"></AlternatingItemStyle>
                        <SeparatorStyle BackColor="LightSkyBlue"></SeparatorStyle>
                        <ItemStyle BackColor="#C0C000"></ItemStyle>
                        <ItemTemplate>
                            nom :
                            <%# Container.DataItem("ad") %>
                            , prix :
                            <%# databinder.eval(Container.DataItem,"fiyat","{0:C}") %>
                            <BR>
                        </ItemTemplate>
                        <SeparatorTemplate>
                            <HR width="100%" SIZE="1">
                        </SeparatorTemplate>
                        <HeaderStyle BackColor="#C0C0FF"></HeaderStyle>
                    </asp:DataList></P>
            </asp:Panel>
            <asp:Panel id="vueErreurs" runat="server">
                <P>Les erreurs suivantes se sont produites :</P>
                <%= erreursHTML %>
            </asp:Panel>
        </form>
    </body>
</HTML>

8.7.4. [DataList] bileşenlerinin yapılandırılması

[DataList] bileşeninin çeşitli özelliklerine bir göz atalım. Bu özelliklerin sayısı oldukça fazladır ve burada sadece küçük bir kısmını sunuyoruz. Bir [DataList] içinde yedi adede kadar görüntüleme şablonu tanımlanabilir:

HeaderTemplate
[DataList] başlık şablonu
ItemTemplate
İlişkili veri listesindeki öğeleri gösteren satırların şablonu. Yalnızca bu şablon zorunludur.
AlternatingItemTemplate
Görüntülenen ardışık öğeleri görsel olarak ayırt etmek için iki şablon kullanılabilir: n numaralı öğe için ItemTemplate, n+1 numaralı öğe için AlternatingItemTemplate
SelectedItemTemplate
[DataList]'te seçilen öğenin şablonu
SeparatorTemplate
[DataList]'teki iki öğe arasındaki ayırıcı şablonu
EditItemTemplate
[DataList], görüntülediği değerlerin değiştirilmesini mümkün kılar. [EditItemTemplate], "düzenleme" modunda olan [DataList]'teki bir öğenin şablonudur
FooterTemplate
[DataList]'in altbilgi şablonu

[DataList1] bileşeni, [WebMatrix] kullanılarak oluşturulmuştur. Özellikler penceresinde [Mise en forme automatique] bağlantısı seçilmiştir:

1234567

Yukarıdaki şemada, [Couleur 5] şablonu, aşağıdaki şablonlar için stiller içeren bir [DataList] şablonu oluşturacaktır: HeaderTemplate (1), ItemTemplate (2, 6), AlternatingTemplate (3, 5), SelectedItemTemplate (4), FooterTemplate (7). Oluşturulan kod şöyledir:


                    <asp:DataList id="DataList1" runat="server" BorderColor="Tan" BorderWidth="1px" BackColor="LightGoldenrodYellow"
                        CellPadding="2" ForeColor="Black">
                        <SelectedItemStyle ForeColor="GhostWhite" BackColor="DarkSlateBlue"></SelectedItemStyle>
                        <AlternatingItemStyle BackColor="PaleGoldenrod"></AlternatingItemStyle>
                        <FooterStyle BackColor="Tan"></FooterStyle>
                        <HeaderStyle Font-Bold="True" BackColor="Tan"></HeaderStyle>
                    </asp:DataList></P>

Hiçbir şablon tanımlanmamıştır. Bunu bizim yapmamız gerekiyor. Aşağıdaki şablonları tanımlıyoruz:

HeaderTemplate

                        <HeaderTemplate>
                            Contenu de la table [liste] de la base [produits]
                        </HeaderTemplate>
ItemTemplate

                        <ItemTemplate>
                            nom :
                            <%# Container.DataItem("ad") %>
                            <br>
                            prix :
                            <%# DataBinder.Eval(Container.DataItem,"fiyat","{0:C}") %>
                            <br>
                        </ItemTemplate>

[ItemTemplate] modelinin, [DataList] ile bağlantılı veri kaynağındaki öğeleri görüntüleyen model olduğunu hatırlatmak isteriz. Bu veri kaynağı, her biri bir veya daha fazla değer içeren bir dizi veri satırından oluşur. Veri kaynağının geçerli satırı, [Container.DataItem] nesnesi ile temsil edilir. Bu tür bir satırın sütunları vardır. [Container.DataItem("col1")], geçerli satırın "col1" sütunundaki değerdir. Bu değeri sunum koduna dahil etmek için <%# Container.DataItem("col") %> yazılır. Bazen, geçerli satırdaki bir öğeyi özel bir biçimde sunmak istenir. Burada, geçerli satırın "fiyat" sütununu euro cinsinden görüntülemek istiyoruz. Bunun için üç parametre kabul eden [DataBinder.Eval] işlevini kullanırız:

  • geçerli satır [Container.DataItem]
  • biçimlendirilecek sütunun adı
  • {0:format} biçimindeki biçimlendirme dizesi; burada [format], [string.format] yöntemi tarafından kabul edilen biçimlerden biridir.

Böylece <%# DataBinder.Eval(Container.DataItem,"fiyat",{0:C}) %> kodu, geçerli satırdaki [prix] sütununu para birimi biçiminde (C=Currency formatı) görüntüleyecektir.

Böylece, şu şekilde görünecek bir [DataList] elde edeceğiz:

Image

Yukarıda, veriler satır başına dört veri olacak şekilde yerleştirilmiştir. Bu, [DataList]'in aşağıdaki öznitelikleriyle elde edilir:

RepeatDirection
Yatay
RepeatColumns
istenen sütun sayısı

Sonuç olarak, [DataList1] kodu, biraz yukarıda sunum kodunda gösterilen koddur. [DataList2]'in sunum kodunu incelemek okuyucuya bırakılmıştır. [DataGrid] bileşeninde olduğu gibi, [DataList]'in özelliklerinin çoğu, [WebMatrix]'in sihirbazı kullanılarak ayarlanabilir. Bunun için, [DataList]'in özellikler penceresindeki [Générateur de propriétés] bağlantısı kullanılır:

8.7.5. Denetleyiciler

[global.asax, global.asax.vb] denetleyicisi şöyledir:

[global.asax]

<%@ Application src="global.asax.vb" inherits="Global" %>

[global.asax.vb]


Imports System
Imports System.Web
Imports System.Web.SessionState
Imports st.istia.univangers.fr
Imports System.Configuration
Imports System.Data
Imports System.Collections

Public Class Global
    Inherits System.Web.HttpApplication

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' bir ürün nesnesi oluşturulur
        Try
            Dim données As DataSet = New produits(ConfigurationSettings.AppSettings("OLEDBStringConnection")).getDataSet("select * from LISTE")
            ' nesne uygulamaya eklenir
            Application("données") = données
            ' hata yok
            Application("erreur") = False
        Catch ex As Exception
            'hata oluştu, uygulamaya kaydedilir
            Application("erreur") = True
            Application("message") = ex.Message
        End Try
    End Sub
End Class

Uygulama başlatıldığında (Application_Start), [produits] iş sınıfından bir [dataset] oluştururuz ve bunu uygulamaya yerleştiririz; böylece tüm istemcilerin tüm istekleri için kullanılabilir hale gelir. Bu oluşturma işlemi sırasında bir istisna oluşursa, bu durum uygulamada kaydedilir. [Application_Start] prosedürü yalnızca bir kez çalıştırılır. Bundan sonra [global.asax] denetleyicisi artık devreye girmeyecektir. Bu durumda işi [main.aspx.vb] denetleyicisi üstlenecektir:


Imports System.Collections
Imports Microsoft.VisualBasic
Imports System.Data
Imports st.istia.univangers.fr
Imports System
Imports System.Xml

Public Class main
    Inherits System.Web.UI.Page

    ' sayfa bileşenleri
    Protected WithEvents vueErreurs As System.Web.UI.WebControls.Panel
    Protected WithEvents DataList1 As System.Web.UI.WebControls.DataList
    Protected WithEvents DataList2 As System.Web.UI.WebControls.DataList
    Protected WithEvents vueRésultats1 As System.Web.UI.WebControls.Panel
    Protected WithEvents vueRésultats2 As System.Web.UI.WebControls.Panel
    Protected WithEvents RadioButton1 As System.Web.UI.WebControls.RadioButton
    Protected WithEvents RadioButton2 As System.Web.UI.WebControls.RadioButton
    Protected WithEvents btnChanger As System.Web.UI.WebControls.Button
    Protected WithEvents bandeau As System.Web.UI.WebControls.Panel
    ' sayfa verileri
    Protected erreursHTML As String

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' uygulamada hata olup olmadığına bakılıyor
        If CType(Application("erreur"), Boolean) Then
            ' uygulama düzgün bir şekilde başlatılamadı
            Dim erreurs As New ArrayList
            erreurs.Add("Application momentanément indisponible (" + CType(Application("message"), String) + ")")
            afficheErreurs(erreurs, False)
            Exit Sub
        End If
        'ilk istek
        If Not IsPostBack Then
            ' kontroller başlatılıyor
            With DataList1
                .DataSource = CType(Application("données"), DataSet)
                .DataBind()
            End With
            With DataList2
                .DataSource = CType(Application("données"), DataSet)
                .DataBind()
            End With
            ' boş form görüntüleniyor
            afficheRésultats(True, False)
        End If
    End Sub

    Private Sub afficheErreurs(ByVal erreurs As ArrayList, ByVal afficheLien As Boolean)
        ' hata görünümünü görüntülüyor
        erreursHTML = ""
        For i As Integer = 0 To erreurs.Count - 1
            erreursHTML += "<li>" + erreurs(i).ToString + "</li>" + ControlChars.CrLf
        Next
        ' [erreurs] görünümü görüntüleniyor
        vueErreurs.Visible = True
        vueRésultats1.Visible = False
        vueRésultats2.Visible = False
        bandeau.Visible = False
    End Sub

    Private Sub afficheRésultats(ByVal visible1 As Boolean, ByVal visible2 As Boolean)
        ' [résultats] görünümünü görüntüler
        vueRésultats1.Visible = visible1
        vueRésultats2.Visible = visible2
        vueErreurs.Visible = False
    End Sub

    Private Sub btnChanger_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnChanger.Click
        ' stil değiştiriliyor
        afficheRésultats(RadioButton1.Checked, RadioButton2.Checked)
    End Sub
End Class

8.8. Tekrarlayıcı Bileşeni ve Veri Bağlantısı

[Repeater] bileşeni, bir veri listesindeki her bir öğenin HTML kodunu tekrarlamayı sağlar. Bir hata listesini aşağıdaki biçimde görüntülemek istediğimizi varsayalım:

Image

Bu sorunla daha önce karşılaştık ve bunu, sunum koduna <ul><% =erreursHTML %></ul> biçiminde bir değişken ekleyerek çözdük; burada erreursHTML değeri denetleyici tarafından hesaplanıyor. Bu değer, bir listeye ait olan HTML kodunu içerir. Bunun dezavantajı, HTML listesinin sunumunu değiştirmek istediğimizde denetleyici kısmına gitmek zorunda kalmamızdır; bu da denetleyici/sunum ayrımına aykırıdır. [Repeater] bileşeni bize bir çözüm sunar. [DataList]'te olduğu gibi, başlık için <HeaderTemplate>, veri listesinin geçerli öğesi için <ItemTemplate> ve verilerin sonu için <FooterTemplate> şablonlarını tanımlayabiliriz. Burada, [Repeater] bileşeni için şu tanım olabilir:

            <asp:Repeater id="Repeater1" runat="server" EnableViewState="False">
                <HeaderTemplate>
                    Les erreurs suivantes se sont produites :
                    <ul>
                </HeaderTemplate>
                <ItemTemplate>
                    <li>
                        <%# Container.DataItem %>
                    </li>
                </ItemTemplate>
                <FooterTemplate>
                    </ul>
                </FooterTemplate>
            </asp:Repeater>

Veri kaynağında birden fazla sütun varsa, [Container.DataItem] bir veri satırını temsil eder. Kaynakta tek bir sütun varsa, bir veri değerini temsil eder. Bu örnekte durum böyledir. Örnek olarak, aşağıdaki uygulamayı oluşturuyoruz:

Image

Sayfanın sunum kodu şöyledir:

<html>
<head>
</head>
<body>
    <form runat="server">
        <p>
            Liaison de données avec un composant [Repeater]
        </p>
        <hr />
        <p>
            <asp:Repeater id="Repeater1" runat="server" EnableViewState="False">
                <ItemTemplate>
                    <li>
                        <%# Container.DataItem %>
                    </li>
                </ItemTemplate>
                <HeaderTemplate>
                    Les erreurs suivantes se sont produites :
                    <ul>
                </HeaderTemplate>
                <FooterTemplate>
                    </ul>
                </FooterTemplate>
            </asp:Repeater>
        </p>
    </form>
</body>
</html>

Doğrulama kodu şöyledir:

<%@ Page Language="VB" %>
<script runat="server">

     ' sayfa yüklendiğinde yürütülen işlem
    Sub page_Load(sender As Object, e As EventArgs)
        if not IsPostBack then
          ' bir veri kaynağı oluşturulur
          with Repeater1
              .DataSource=createDataSource
              .DataBind
          end with
        end if
    End Sub

    function createDataSource as ArrayList
      ' bir arraylist oluşturulur
      dim erreurs as new ArrayList
      dim i as integer
      for i=0 to 5
        erreurs.add("erreur-"+i.ToString)
      next
      return erreurs
    end function

</script>
<html>
...
</html>

Müşterinin ilk isteği üzerine, bir hata listesini temsil ettiği varsayılan [Repeater] bileşenine [ArrayList] nesnesini eşliyoruz.

8.9. Application

Burada, daha önce sunucu bileşenleriyle işlenmiş bir uygulamayı ele alıyoruz. Uygulama, vergi hesaplamaları simülasyonları yapmaya olanak tanır. Uygulama, burada tekrar üzerinde durmayacağımız [impot] sınıfına dayanmaktadır. Bu sınıf, OLEDB veri kaynağında bulunan verilere ihtiyaç duyar. Örnek olarak, ACCESS veri kaynağı kullanılacaktır. Bu yeni sürümde aşağıdaki yenilikleri sunuyoruz:

  • verilerin geçerliliğini kontrol etmek için doğrulama bileşenlerinin kullanımı
  • sonuçların görüntülenmesi için veri kaynaklarına bağlı sunucu bileşenlerinin kullanımı

8.9.1. Uygulamanın MVC yapısı

Uygulamanın MVC yapısı şu şekildedir:

Bu üç görünüm, [main.aspx] denetleyicisinin sunum koduna konteynerler şeklinde eklenecektir. Dolayısıyla bu uygulamanın tek bir sayfası vardır: [main.aspx].

8.9.2. Uygulamanın görünümleri

[formulaire] görünümü, bir kullanıcının vergisinin hesaplanmasına olanak tanıyan bilgi giriş formudur:

Image

Kullanıcı formu doldurur:

Image

[Envoyer] düğmesini kullanarak vergisinin hesaplanmasını talep eder. Aşağıdaki [simulations] görünümünü alır:

Image

Yukarıdaki bağlantı aracılığıyla forma geri döner. Formu, girdiğindeki haliyle bulur. Giriş yaparken hatalar yapabilir:

Image

Bu hatalar, [formulaire] ekranında kendisine bildirilir:

Image

Kullanıcı daha sonra hatalarını düzeltir. Yeni simülasyonlar yapabilir:

Image

Böylece, bir simülasyon daha eklenmiş olan [simulations] görünümünü elde eder:

Image

Son olarak, veri kaynağı mevcut değilse, bu durum [erreurs] görünümünde kullanıcıya bildirilir:

Image

8.9.2.1. Sunum kodu

[main.aspx] sayfasının tüm görünümleri bir araya getirdiğini hatırlayalım. Bu, üç kapsayıcı içeren tek bir formdur:

  • [panelform], [formulaire] görünümü için
  • [panelerreurs], [erreurs] görünümü için
  • [panelsimulations], [simulations] görünümü için

Şimdi bu üç konteynerin bileşenlerini ayrıntılı olarak inceleyeceğiz. [panelform] konteynerinin görsel gösterimi şöyledir:

no
ad
tür
özellikler
rol
0
panelform
Panel
 
form görünümü
1
rdOui
rdNon
RadioButton
GroupName=rdmarie
radyo düğmeleri
2
cvMarie
CustomValidator
ErrorMessage=Medeni durumunuzu belirtmediniz
EnableClientScript=false
istemci programının beklenen medeni durumu gönderdiğini kontrol eder
3
txtEnfants
TextBox
 
çocuk sayısı
4
rfvEnfants
RequiredFieldValidator
ErrorMessage=Çocuk sayısını belirtin
ControlToValidate=txtEnfants
[txtEnfants] alanının boş olmadığını kontrol eder
5
rvEnfants
RangeValidator
ErrorMessage=1 ile 30 arasında bir sayı girin
ControlToValidate=txtEnfants
[txtEnfants] alanının [1,30] aralığında olup olmadığını kontrol eder
6
txtSalaire
TextBox
EnableViewState=true
yıllık maaş
7
rfvSalaire
RequiredFieldValidator
ControlToValidate=txtMaaş
ErrorMessage=Maaş tutarınızı girin
[txtSalaire] alanının boş olmadığını kontrol eder
8
revSalaire
RegularExpressionValidator
ControlToValidate=txtMaaş
ErrorMessage=Geçersiz maaş
RegularExpression=\s*\d+\s*
[txtSalaire] alanının sadece rakamlardan oluştuğunu kontrol eder
9
btnCalculer
Düğme
CausesValidation=true
formdaki [submit] düğmesi - vergi hesaplamasını başlatır
10
btnEffacer
Düğme
CausesValidation=false
Formdaki [submit] düğmesi - formu boşaltır

Kullanıcının iki radyo düğmesinden birini işaretlediğini doğrulamakla görevli [cvMarié] denetimi şaşırtıcı gelebilir. Aslında, sunucu tarafından gönderilen formu doğru kullanıyorsa başka türlü olması mümkün değildir. Bunu garanti edecek hiçbir şey olmadığından, gönderilen tüm parametreleri doğrulamak zorundayız. Ayrıca, [btnEffacer] düğmesinin [CausesValidation=false] özniteliğine de dikkat edilmelidir. Zira kullanıcı bu düğmeyi kullandığında, gönderilen veriler göz ardı edileceği için kontrol edilmemelidir.

[panelForm, txtEnfants, txtSalaire, rdOui, rdNon] hariç, konteynerin tüm bileşenleri [EnableViewState=false] özelliğine sahiptir. [panelerreurs] konteynerinin görsel temsili şöyledir:

no
ad
tür
özellikler
rol
0
panelerreurs
Panel
EnableViewState=false
hata görünümü
1
rptErreurs
Tekrarlayıcı
EnableViewState=false
bir hata listesi görüntüler

[rptErreurs] bileşeni şu şekilde tanımlanmıştır:


                <asp:Repeater id="rptErreurs" runat="server" EnableViewState="False">
                    <ItemTemplate>
                        <li>
                            <%# Container.Dataitem%>
                        </li>
                    </ItemTemplate>
                    <HeaderTemplate>
                        Les erreurs suivantes se sont produites
                        <ul>
                    </HeaderTemplate>
                    <FooterTemplate>
                        </ul>
                    </FooterTemplate>
                </asp:Repeater>

[rptErreurs] bileşeniyle ilişkili veri listesi, bir hata mesajları listesi içeren [ArrayList] nesnesi olacaktır. Dolayısıyla yukarıda, <%# Container.Dataitem%> mevcut hata mesajını belirtir. [panelsimulations] kapsayıcısının görsel gösterimi şöyledir:

no
ad
tür
özellikler
rol
0
panelsimulations
Panel
EnableViewState=false
simülasyonlar görünümü
2
lnkForm2
LinkButton
EnableViewState=false
form bağlantısı
1
dgSimulations
DataGrid
EnableViewState=false
[DataTable] nesnesine yerleştirilen simülasyonları görüntülemekle görevlidir

[dgSimulations] bileşeni, [Webmatrix] altında aşağıdaki şekilde yapılandırılmıştır. [dgSimulations] özellik penceresinde, [Mise en forme automatique] bağlantısını seçip [Couleur 3] şemasını seçiyoruz:

Ardından, yine [dlgSimulations]'in özellikler penceresinde, [Générateur de propriétés] bağlantısını seçiyoruz. Sütun başlıklarının görüntülenmesini istiyoruz:

Image

[DataGrid]'in dört sütununu tanımlamak için [Colonnes] seçeneğini seçiyoruz:

Image

[Créer des colonnes automatiquement ...] ifadesinin işaretini kaldırıyoruz. [DataGrid]'in dört sütununu kendimiz tanımlayacağız. Bu, sırasıyla "evli", "çocuklar", "maaş", "vergi" olarak adlandırılmış dört sütuna sahip bir [DataTable] nesnesiyle ilişkilendirilecektir. [DataGrid]'te bir sütun oluşturmak için, [Colonnes connexe] seçeneğini seçip yukarıda gösterildiği gibi oluşturma düğmesini kullanıyoruz. Bir sütun oluşturulur ve özelliklerini tanımlayabiliriz. Simülasyon tablosunun ilk sütunu, [DataGrid] ile ilişkilendirilecek olan [DataTable] nesnesinin "evli" sütununu içerecektir. [DataGrid]'in bu ilk sütunu, sihirbazda şu şekilde tanımlanır:

Image

Texte de l'en-tête
sütun başlığı, burada "Evli"
Champ de données
[DataGrid]'in bu sütunu tarafından görüntülenecek veri kaynağındaki sütun adı. Burada, [DataTable]'in "evli" sütunudur.

İkinci sütun şu şekilde tanımlanmıştır:

Texte de l'en-tête
Çocuklar
Champ de données
çocuklar

Üçüncü sütun şu şekilde tanımlanmıştır:

Texte de l'en-tête
Yıllık maaş
Champ de données
maaş
Expression de mise en forme
{0:C} - euro sembolünü elde etmek için para birimi gösterimi

Dördüncü sütun şu şekilde tanımlanmıştır:

Texte de l'en-tête
Vergi tutarı
Champ de données
vergi
Expression de mise en forme
{0:C} - euro işaretini elde etmek için para birimi gösterimi

Görünüm kodunu ve kontrol kodunu iki ayrı dosyaya yerleştiriyoruz. İlki [main.aspx] dosyasında, ikincisi ise [main.aspx.vb] dosyasında yer alacaktır. [main.aspx] kodunun içeriği şöyledir:


<%@ page src="main.aspx.vb" inherits="main" AutoEventWireUp="false" %>
<HTML>
    <HEAD>
        <title>Calculer votre impôt</title>
    </HEAD>
    <body>
        <P>Calculer votre impôt</P>
        <HR width="100%" SIZE="1">
        <FORM id="Form1" runat="server">

            <asp:panel id="panelform" Runat="server">
                <TABLE id="Table1" cellSpacing="1" cellPadding="1" border="0">
                    <TR>
                        <TD height="19">Etes-vous marié(e)</TD>
                        <TD height="19">
                            <asp:RadioButton id="rdOui" runat="server" GroupName="rdMarie"></asp:RadioButton>Oui
                            <asp:RadioButton id="rdNon" runat="server" GroupName="rdMarie" Checked="True"></asp:RadioButton>Non
                            <asp:CustomValidator id="cvMarie" runat="server" ErrorMessage="Vous n'avez pas indiqué votre état marital"
                                Display="Dynamic" EnableClientScript="False" Visible="False" EnableViewState="False"></asp:CustomValidator></TD>
                    </TR>
                    <TR>
                        <TD>Nombre d'enfants</TD>
                        <TD>
                            <asp:TextBox id="txtEnfants" runat="server" Columns="3" MaxLength="3"></asp:TextBox>
                            <asp:RequiredFieldValidator id="rfvEnfants" runat="server" ErrorMessage="Indiquez le nombre d'enfants" Display="Dynamic"
                                ControlToValidate="txtEnfants" EnableViewState="False"></asp:RequiredFieldValidator>
                            <asp:RangeValidator id="rvEnfants" runat="server" ErrorMessage="Tapez un nombre entre 1 et 30" Display="Dynamic"
                                ControlToValidate="txtEnfants" Type="Integer" MaximumValue="30" MinimumValue="0" EnableViewState="False"></asp:RangeValidator></TD>
                    </TR>
                    <TR>
                        <TD>Salaire annuel (euro)</TD>
                        <TD>
                            <asp:TextBox id="txtSalaire" runat="server" Columns="10" MaxLength="10"></asp:TextBox>
                            <asp:RequiredFieldValidator id="rfvSalaire" runat="server" ErrorMessage="Indiquez le montant de votre salaire"
                                Display="Dynamic" ControlToValidate="txtSalaire" EnableViewState="False"></asp:RequiredFieldValidator>
                            <asp:RegularExpressionValidator id="revSalaire" runat="server" ErrorMessage="Salaire invalide" Display="Dynamic"
                                ControlToValidate="txtSalaire" ValidationExpression="\s*\d+\s*" EnableViewState="False"></asp:RegularExpressionValidator></TD>
                    </TR>
                </TABLE>
                <P>
                    <asp:Button id="btnCalculer" runat="server" Text="Calculer"></asp:Button>
                    <asp:Button id="btnEffacer" runat="server" Text="Effacer" CausesValidation="False"></asp:Button></P>
            </asp:panel>

             <asp:panel id="panelerreurs" runat="server" EnableViewState="False">
                <asp:Repeater id="rptErreurs" runat="server" EnableViewState="False">
                    <ItemTemplate>
                        <li>
                            <%# Container.Dataitem%>
                        </li>
                    </ItemTemplate>
                    <HeaderTemplate>
                        Les erreurs suivantes se sont produites
                        <ul>
                    </HeaderTemplate>
                    <FooterTemplate>
                        </ul>
                    </FooterTemplate>
                </asp:Repeater>
            </asp:panel>
 
          <asp:panel id="panelsimulations" runat="server" EnableViewState="False">
                <P>
                    <asp:DataGrid id="dgSimulations" runat="server" BorderColor="#DEBA84" BorderStyle="None" CellSpacing="2"
                        BorderWidth="1px" BackColor="#DEBA84" CellPadding="3" AutoGenerateColumns="False" EnableViewState="False">
                        <SelectedItemStyle Font-Bold="True" ForeColor="White" BackColor="#738A9C"></SelectedItemStyle>
                        <ItemStyle ForeColor="#8C4510" BackColor="#FFF7E7"></ItemStyle>
                        <HeaderStyle Font-Bold="True" ForeColor="White" BackColor="#A55129"></HeaderStyle>
                        <FooterStyle ForeColor="#8C4510" BackColor="#F7DFB5"></FooterStyle>
                        <Columns>
                            <asp:BoundColumn DataField="mari&#233;" HeaderText="Mari&#233;"></asp:BoundColumn>
                            <asp:BoundColumn DataField="enfants" HeaderText="Enfants"></asp:BoundColumn>
                            <asp:BoundColumn DataField="salaire" HeaderText="Salaire annuel" DataFormatString="{0:C}"></asp:BoundColumn>
                            <asp:BoundColumn DataField="imp&#244;t" HeaderText="Montant de l'imp&#244;t" DataFormatString="{0:C}"></asp:BoundColumn>
                        </Columns>
                        <PagerStyle HorizontalAlign="Center" ForeColor="#8C4510" Mode="NumericPages"></PagerStyle>
                    </asp:DataGrid></P>
                <P>
                    <asp:LinkButton id="lnkForm2" runat="server" EnableViewState="False">Retour au formulaire</asp:LinkButton></P>
            </asp:panel>

      </FORM>
    </body>
</HTML>

8.9.3. Uygulamanın kontrol kodu

Uygulamanın kontrol kodu, [global.asax.vb] ve [main.aspx.vb] dosyalarında yer almaktadır. [global.asax] dosyası şu şekilde tanımlanmıştır:

<%@ Application src="Global.asax.vb" Inherits="Global" %>

[global.asax.vb] dosyası şu şekildedir:


Imports System
Imports System.Web
Imports System.Web.SessionState
Imports st.istia.univangers.fr
Imports System.Configuration
Imports System.Collections
Imports System.Data

Public Class Global
    Inherits System.Web.HttpApplication

    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' bir impo nesnesi oluşturulur
        Dim objImpot As impot
        Try
            objImpot = New impot(New impotsOLEDB(ConfigurationSettings.AppSettings("chaineConnexion")))
            ' nesneyi uygulamaya eklenir
            Application("objImpot") = objImpot
            ' hata yok
            Application("erreur") = False
        Catch ex As Exception
            'hata oluştu, bunu uygulamaya kaydediyoruz
            Application("erreur") = True
            Application("message") = ex.Message
        End Try
    End Sub

    Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
        ' oturumun başlangıcı - boş bir simülasyon listesi oluşturulur
        Dim simulations As New DataTable("simulations")
        simulations.Columns.Add("marié", Type.GetType("System.String"))
        simulations.Columns.Add("enfants", Type.GetType("System.String"))
        simulations.Columns.Add("salaire", Type.GetType("System.Int32"))
        simulations.Columns.Add("impôt", Type.GetType("System.Int32"))
        Session.Item("simulations") = simulations
    End Sub
End Class

Uygulama başlatıldığında (uygulamaya yapılan ilk istek), [Application_Start] prosedürü yürütülür. Bu prosedür, verilerini OLEDB kaynağından alan [impot] türünde bir nesne oluşturmaya çalışır. Okuyucu, bu sınıfın tanımlandığı 5. bölümü, unutmuşsa, okumasını öneririz. Veri kaynağı mevcut değilse, [impot] nesnesinin oluşturulması başarısız olabilir. Bu durumda, hata uygulamada kaydedilir; böylece sonraki tüm sorgular, nesnenin düzgün bir şekilde başlatılamadığını bilir. Oluşturma işlemi başarılı olursa, oluşturulan [impot] nesnesi de uygulamada kaydedilir. Bu nesne, tüm vergi hesaplama sorguları tarafından kullanılacaktır. Bir müşteri ilk isteğini yaptığında, [Application_Start] yordamı tarafından kendisi için bir oturum oluşturulur. Bu oturum, müşterinin yapacağı çeşitli vergi hesaplama simülasyonlarını kaydetmek amacıyla kullanılır. Bu simülasyonlar, "simulations" oturum anahtarıyla ilişkilendirilmiş bir [DataTable] nesnesinde saklanacaktır. Oturum başladığında, bu anahtar, yapısı önceden tanımlanmış ancak içeriği boş olan bir [DataTable] nesnesine eşleştirilir. Uygulama için gerekli bilgiler, [wenConfig] yapılandırma dosyasına yerleştirilir:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="chaineConnexion" value="Provider=Microsoft.Jet.OLEDB.4.0; Ole DB Services=-4; Data Source=D:\data\devel\aspnet\poly\webforms2\vs\impots6\impots.mdb" />
    </appSettings>
</configuration>

[chaineConnexion] anahtarı, OLEDB kaynağına bağlantı dizesini belirtir. Kontrol kodunun diğer kısmı [main.aspx.vb]'te bulunur:


Imports System.Collections
Imports Microsoft.VisualBasic
Imports st.istia.univangers.fr
Imports System
Imports System.Web.UI.Control
Imports System.Data

Public Class main
    Inherits System.Web.UI.Page

    Protected WithEvents rdOui As System.Web.UI.WebControls.RadioButton
    Protected WithEvents rdNon As System.Web.UI.WebControls.RadioButton
    Protected WithEvents txtEnfants As System.Web.UI.WebControls.TextBox
    Protected WithEvents txtSalaire As System.Web.UI.WebControls.TextBox
    Protected WithEvents btnCalculer As System.Web.UI.WebControls.Button
    Protected WithEvents btnEffacer As System.Web.UI.WebControls.Button
    Protected WithEvents panelform As System.Web.UI.WebControls.Panel
    Protected WithEvents lnkForm2 As System.Web.UI.WebControls.LinkButton
    Protected WithEvents panelerreurs As System.Web.UI.WebControls.Panel
    Protected WithEvents rfvEnfants As System.Web.UI.WebControls.RequiredFieldValidator
    Protected WithEvents rvEnfants As System.Web.UI.WebControls.RangeValidator
    Protected WithEvents rfvSalaire As System.Web.UI.WebControls.RequiredFieldValidator
    Protected WithEvents rptErreurs As System.Web.UI.WebControls.Repeater
    Protected WithEvents dgSimulations As System.Web.UI.WebControls.DataGrid
    Protected WithEvents revSalaire As System.Web.UI.WebControls.RegularExpressionValidator
    Protected WithEvents cvMarie As System.Web.UI.WebControls.CustomValidator
    Protected WithEvents panelsimulations As System.Web.UI.WebControls.Panel

    ' yerel değişkenler

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
...
    End Sub

    Private Sub afficheErreurs(ByRef erreurs As ArrayList)
...
    End Sub

    Private Sub afficheFormulaire()
...
    End Sub

    Private Sub afficheSimulations(ByRef simulations As DataTable, ByRef lien As String)
...
    End Sub

    Private Sub btnCalculer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalculer.Click
....
    End Sub

    Private Sub lnkForm1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
...
    End Sub

    Private Sub lnkForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lnkForm2.Click
...
    End Sub

    Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEffacer.Click
...
    End Sub

    Private Sub razForm()
...
    End Sub

    Private Sub cvMarie_ServerValidate(ByVal source As System.Object, ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs)
...
    End Sub
End Class

Kod tarafından işlenen ilk olay [Page_Load]'tir:


    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' öncelikle, uygulamanın durumuna bakılıyor
        If CType(Application("erreur"), Boolean) Then
            ' uygulama başlatılamadı
            ' hata görünümünü görüntülüyoruz
            Dim erreurs As New ArrayList
            erreurs.Add("Application momentanément indisponible (" + CType(Application("message"), String) + ")")
            afficheErreurs(erreurs)
            Exit Sub
        End If
        ' hata yok - ilk istekte form görüntülenir
        If Not IsPostBack Then afficheFormulaire()
    End Sub

İsteği işlemeye başlamadan önce, uygulamanın düzgün bir şekilde başlatılabildiğinden emin oluruz. Aksi takdirde, [erreurs] görünümünü [afficheErreurs] prosedürüyle görüntüleriz. Eğer bu ilk istekse (IsPostBack=false), [afficheFormulaire] ile [formulaire] görünümünü görüntüleriz.

[erreurs] görünümünü görüntüleyen prosedür şöyledir:


    Private Sub afficheErreurs(ByRef erreurs As ArrayList)
        ' hata listesi oluşturulur
        With rptErreurs
            .DataSource = erreurs
            .DataBind()
        End With
        ' konteynerler görüntüleniyor 
        panelerreurs.Visible = True
        panelform.Visible = False
        panelsimulations.Visible = False
        Exit Sub
    End Sub

Prosedür, [erreurs]'te bulunan [ArrayList] türündeki hata mesajları listesini parametre olarak alır. Bu veri kaynağını, görüntüleme görevini üstlenen [rptErreurs] bileşenine bağlamamız yeterlidir.

[formulaire] görünümünü görüntüleyen prosedür şöyledir:


    Private Sub afficheFormulaire()
        ' formu görüntüler
        panelform.Visible = True
        ' diğer konteynerler gizlenir
        panelerreurs.Visible = False
        panelsimulations.Visible = False
    End Sub

Bu prosedür, yalnızca [panelform] konteynerini görünür hale getirir. Bileşenler, gönderilen veya önceki değerleriyle (VIEWSTATE) görüntülenir.

Kullanıcı, [formulaire] görünümündeki [Calculer] düğmesine tıkladığında, POST'ten [main.aspx]'e bir geçiş yapılır. [Page_Load] prosedürü çalıştırılır, ardından [btnCalculer_Click] prosedürü çalıştırılır:


    Private Sub btnCalculer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCalculer.Click
        ' girilen verilerin geçerliliği kontrol edilir, hata varsa bildirilir
        If Not Page.IsValid Then
            afficheFormulaire()
            Exit Sub
        End If
        ' hata yok - vergi hesaplanır
        Dim impot As Long = CType(Application("objImpot"), impot).calculer( _
        rdOui.Checked, CType(txtEnfants.Text, Integer), CType(txtSalaire.Text, Long))
        ' sonuç mevcut simülasyonlara eklenir
        Dim simulations As DataTable = CType(Session.Item("simulations"), DataTable)
        Dim simulation As DataRow = simulations.NewRow
        simulation("marié") = CType(IIf(rdOui.Checked, "oui", "non"), String)
        simulation("enfants") = txtEnfants.Text.Trim
        simulation("salaire") = CType(txtSalaire.Text.Trim, Long)
        simulation("impôt") = impot
        simulations.Rows.Add(simulation)
        ' simülasyonlar oturuma eklenir
        Session.Item("simulations") = simulations
        ' simülasyonlar sayfası görüntülenir
        afficheSimulations(simulations, "Retour au formulaire")
    End Sub

İşlem, sayfanın geçerliliğinin kontrol edilmesiyle başlar. Burada şunu hatırlatmak gerekir ki, [btnCalculer_Click] işlemi yürütüldüğünde, geçerlilik kontrolleri tamamlanmış ve sayfanın [IsValid] özniteliği ayarlanmış olur. Sayfa geçerli değilse, [formulaire] görünümü yeniden görüntülenir ve işlem sonlandırılır. [formulaire] görünümündeki, [IsValid] ile [false] arasında bir değere sahip olan doğrulama bileşenleri, [ErrorMessage] özniteliğini gösterecektir. Sayfa geçerliyse, vergi tutarı, uygulamanın başlatılması sırasında uygulamada depolanmış olan [impot] türündeki nesne kullanılarak hesaplanır. Bu yeni simülasyon, daha önce yapılmış simülasyonlar listesine eklenir ve oturumda depolanır.

Son olarak, [simulations] görünümü, aşağıdaki [afficheSimulations] prosedürü tarafından görüntülenir:


    Private Sub afficheSimulations(ByRef simulations As DataTable, ByRef lien As String)
        ' veri tablosunu simülasyon kaynağına bağlanıyor
        With dgSimulations
            .DataSource = simulations
            .DataBind()
        End With
        ' bağlantı
        lnkForm2.Text = lien
        ' görünümler
        panelsimulations.Visible = True
        panelerreurs.Visible = False
        panelform.Visible = False
    End Sub

Bu prosedürün iki parametresi vardır:

  • [simulations]'te bulunan, [DataTable] türünde bir simülasyon listesi
  • [lien]'teki bağlantı metni

[simulations] veri kaynağı, bunu görüntülemekle görevli bileşene bağlıdır. Bağlantı metni ise görünümdeki [LinkButton] nesnesinin [Text] özelliğine yerleştirilir.

Kullanıcı, [formulaire] görünümündeki [Effacer] düğmesine tıkladığında, [btnEffacer_click] yordamı çalıştırılır (her zaman [Page_Load]'ten sonra):


    Private Sub btnEffacer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEffacer.Click
        ' boş formu görüntüler
        razForm()
        afficheFormulaire()
    End Sub

    Private Sub razForm()
        ' formu boşaltır
        rdOui.Checked = False
        rdNon.Checked = True
        txtEnfants.Text = ""
        txtSalaire.Text = ""
    End Sub

Yukarıdaki kod, açıklama gerektirmeyecek kadar basittir. Geriye, [erreurs] ve [simulations] görünümlerindeki bağlantılara yapılan tıklamaları yönetmek kalıyor:


    Private Sub lnkForm1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lnkForm1.Click
        ' formu görüntüler
        afficheFormulaire()
    End Sub

    Private Sub lnkForm2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lnkForm2.Click
        ' formu görüntüler
        afficheFormulaire()
    End Sub

Her iki prosedür de sadece [formulaire] görünümünü görüntülemekle yetinir. Bu formdaki alanların, ya kendileri için gönderilen değerleri ya da önceki değerlerini alacağını biliyoruz. Burada olduğu gibi, müşterinin POST formu, form alanları için herhangi bir değer göndermediğinden, bu alanlar önceki değerlerine geri dönecektir. Dolayısıyla form, kullanıcı tarafından girilen değerlerle görüntülenir.

8.9.4. Testler

Uygulama için gerekli tüm dosyalar <application-path> klasörüne yerleştirilir:
[bin] klasörü, uygulama için gerekli olan [impot], [impotsData] ve [impotsOLEDB] sınıflarını içeren DLL dosyasını barındırır:

İsteyen okuyucular, yukarıdaki [impot.dll] dosyasının nasıl oluşturulacağının açıklandığı 5. bölümü tekrar okuyabilirler. Bu işlem tamamlandıktan sonra, Cassini sunucusu (<application-path>,/impots6) parametreleriyle başlatılır. Bir tarayıcıdan [http://impots6/main.aspx] URL'si çağrılır:

Image

ACCESS adlı dosyayı [impots.mdb]'ten [impots1.mdb] olarak yeniden adlandırırsak, şu sayfa karşımıza çıkar:

Image

8.9.5. Sonuç

Sadece sunucu bileşenlerini kullanan MVC adlı bir uygulamamız var. Bu bileşenlerin kullanımı, uygulamanın sunum kısmını kontrol kısmından tamamen ayırmamızı sağladı. Sunum kodunda, kontrol kodu tarafından hesaplanan ve HTML kodunu içeren bir değere sahip değişkenler bulunduğu için, bu durum şimdiye kadar mümkün değildi. Artık durum böyle değil.