İçerik Sayfalarında Denetim Kimliği Adlandırma (VB)

tarafından Scott Mitchell

PDF'i indirin

ContentPlaceHolder denetimlerinin bir adlandırma kapsayıcısı olarak nasıl çalıştığını ve bu nedenle bir denetimle program aracılığıyla çalışmayı nasıl zorlaştıracaklarını gösterir (FindControl aracılığıyla). Bu soruna ve geçici çözümlere göz atabilirsiniz. Ayrıca, sonuçta elde edilen ClientID değerine program aracılığıyla erişmeyi de açıklar.

Giriş

Tüm ASP.NET sunucu denetimleri, denetimi benzersiz olarak tanımlayan bir ID özellik içerir ve arka planda kod sınıfında denetime program aracılığıyla erişilen araçlardır. Benzer şekilde, bir HTML belgesindeki öğeler öğeyi benzersiz olarak tanımlayan bir id öznitelik içerebilir; bu id değerler genellikle istemci tarafı betiğinde belirli bir HTML öğesine program aracılığıyla başvurmak için kullanılır. Bunu göz önünde bulundurarak, bir ASP.NET sunucu denetimi HTML'de işlendiğinde, değerinin ID işlenen HTML öğesinin id değeri olarak kullanıldığını varsayabilirsiniz. Belirli durumlarda tek bir değere sahip tek bir ID denetim işlenen işaretlemede birden çok kez görüntülenebileceği için bu durum mutlaka böyle değildir. Değeri ProductNameolan Label Web denetimine sahip TemplateField içeren bir ID GridView denetimi düşünün. GridView çalışma zamanında veri kaynağına bağlandığında, bu Etiket her GridView satırı için bir kez yinelenir. İşlenen her Etiket için benzersiz id bir değer gerekir.

bu tür senaryoları işlemek için ASP.NET bazı denetimlerin adlandırma kapsayıcıları olarak belirtilmesine izin verir. Adlandırma kapsayıcısı yeni ID bir ad alanı görevi görür. Adlandırma kapsayıcısında görünen tüm sunucu denetimleri, işlenen id değerlerine adlandırma kapsayıcısı denetiminin ID ön ekini ekler. Örneğin, GridView ve GridViewRow sınıfları kapsayıcıları adlandırmaktır. Sonuç olarak, ile ID ProductName GridView TemplateField içinde tanımlanan Etiket denetimine GridViewID_GridViewRowID_ProductNameişlenmiş id değeri verilir. GridViewRowID her GridView satırı için benzersiz olduğundan, sonuçta elde edilen id değerler benzersizdir.

Not

ArabirimINamingContainer, belirli bir ASP.NET sunucu denetiminin adlandırma kapsayıcısı olarak çalışması gerektiğini belirtmek için kullanılır. Arabirim, INamingContainer sunucu denetiminin uygulaması gereken hiçbir yöntemi belirtmez; bunun yerine işaretçi olarak kullanılır. İşlenen işaretlemeyi oluştururken, bir denetim bu arabirimi uygularsa ASP.NET altyapısı otomatik olarak değerini alt öğesinin işlenen id öznitelik değerlerine ön ek ID olarak ekler. Bu işlem, 2. Adım'da daha ayrıntılı olarak ele alınmıştı.

Kapsayıcıları adlandırmak yalnızca işlenen id öznitelik değerini değiştirmekle kalmaz, aynı zamanda ASP.NET sayfasının arka planda kod sınıfından denetime program aracılığıyla nasıl başvurulabileceğini de etkiler. FindControl("controlID") yöntemi genellikle bir Web denetimine program aracılığıyla başvurmak için kullanılır. Ancak, FindControl adlandırma kapsayıcıları aracılığıyla nüfuz etmez. Sonuç olarak, gridview veya diğer adlandırma kapsayıcısı Page.FindControl içindeki denetimlere başvurmak için yöntemini doğrudan kullanamazsınız.

Sizin de izlendiğiniz gibi, ana sayfalar ve ContentPlaceHolder'lar adlandırma kapsayıcıları olarak uygulanır. Bu öğreticide, ana sayfaların HTML öğesi id değerlerini nasıl etkilediğini ve kullanarak FindControlbir içerik sayfasındaki Web denetimlerine program aracılığıyla başvurmanın yollarını inceleyeceğiz.

1. Adım: Yeni ASP.NET Sayfası Ekleme

Bu öğreticide ele alınan kavramları göstermek için web sitemize yeni bir ASP.NET sayfası ekleyelim. Kök klasörde adlı IDIssues.aspx yeni bir içerik sayfası oluşturun ve bunu ana sayfaya Site.master bağlayın.

İçerik Sayfası IDIssues.aspx Kök Klasöre Ekleme

Şekil 01: İçerik Sayfasını IDIssues.aspx Kök Klasöre Ekleme

Visual Studio, ana sayfanın dört ContentPlaceHolder'ının her biri için otomatik olarak bir İçerik denetimi oluşturur. Birden Çok ContentPlaceHolder ve Varsayılan İçerik öğreticisinde belirtildiği gibi, İçerik denetimi yoksa bunun yerine ana sayfanın varsayılan ContentPlaceHolder içeriği yayılır. QuickLoginUI ve LeftColumnContent ContentPlaceHolder'lar bu sayfa için uygun varsayılan işaretlemeler içerdiğinden, devam edin ve ilgili İçerik denetimlerini 'den IDIssues.aspxkaldırın. Bu noktada, içerik sayfasının bildirim temelli işaretlemesi aşağıdaki gibi görünmelidir:

<%@ Page Language="VB" MasterPageFile="~/Site.master" AutoEventWireup="false" CodeFile="IDIssues.aspx.vb" Inherits="IDIssues" Title="Untitled Page" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" Runat="Server">
</asp:Content>

Ana Sayfadaki Başlık, Meta Etiketler ve Diğer HTML Üst Bilgilerini Belirtme öğreticisinde, açıkça ayarlanmadıysa sayfanın başlığını otomatik olarak yapılandıran özel bir temel sayfa sınıfı (BasePage) oluşturduk. IDIssues.aspx Sayfanın bu işlevi kullanabilmesi için, sayfanın arka planda kod sınıfının sınıfından BasePage türetilmiş olması gerekir (yerineSystem.Web.UI.Page). Arka planda kod sınıfının tanımını aşağıdaki gibi görünecek şekilde değiştirin:

Partial Class IDIssues
 Inherits BasePage

End Class

Son olarak, dosyayı bu yeni ders için bir girdi içerecek şekilde güncelleştirin Web.sitemap . Bir <siteMapNode> öğe ekleyin ve ve title url özniteliklerini sırasıyla "Denetim Kimliği Adlandırma Sorunları" ve ~/IDIssues.aspxolarak ayarlayın. Bu eklemeden sonra dosyanızın Web.sitemap işaretlemesi aşağıdakine benzer görünmelidir:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
 <siteMapNode url="~/Default.aspx" title="Home">
 <siteMapNode url="~/About.aspx" title="About the Author" />
 <siteMapNode url="~/MultipleContentPlaceHolders.aspx" title="Using Multiple ContentPlaceHolder Controls" />
 <siteMapNode url="~/Admin/Default.aspx" title="Rebasing URLs" />
 <siteMapNode url="~/IDIssues.aspx" title="Control ID Naming Issues" />
 </siteMapNode>
</siteMap>

Şekil 2'de gösterildiği gibi, içindeki Web.sitemap yeni site haritası girişi hemen sol sütundaki Dersler bölümüne yansıtılır.

Dersler Bölümü Artık

Şekil 02: Dersler Bölümü Artık "Denetim Kimliği Adlandırma Sorunları" bağlantısını içerir

2. Adım: İşlenenIDDeğişiklikleri inceleme

ASP.NET altyapısının sunucu denetimlerinin işlenmiş id değerlerinde yaptığı değişiklikleri daha iyi anlamak için sayfaya IDIssues.aspx birkaç Web denetimi ekleyelim ve ardından tarayıcıya gönderilen işlenmiş işaretlemeyi görüntüleyelim. Özellikle, "Lütfen yaşınızı girin:" metnini ve ardından bir TextBox Web denetimi yazın. Sayfanın daha aşağı kısmında Düğme Web denetimi ve Etiket Web denetimi ekleyin. TextBox'ın ID ve Columns özelliklerini Age sırasıyla ve 3 olarak ayarlayın. Düğmenin Text ve ID özelliklerini "Gönder" ve SubmitButtonolarak ayarlayın. Label Text özelliğini temizleyin ve olarak ResultsayarlayınID.

Bu noktada İçerik denetiminizin bildirim temelli işaretlemesi aşağıdakine benzer olmalıdır:

<p>
 Please enter your age:
 <asp:TextBox ID="Age" Columns="3" runat="server"></asp:TextBox>
</p>
<p>
 <asp:Button ID="SubmitButton" runat="server" Text="Submit" />
</p>
<p>
 <asp:Label ID="Results" runat="server"></asp:Label>
</p>

Şekil 3'te, Visual Studio'nun tasarımcısı aracılığıyla görüntülendiğinde sayfa gösterilmektedir.

Sayfada Üç Web Denetimi Vardır: TextBox, Düğme ve Etiket

Şekil 03: Sayfada Üç Web Denetimi Vardır: TextBox, Düğme ve Etiket (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Tarayıcı üzerinden sayfayı ziyaret edin ve ardından HTML kaynağını görüntüleyin. Aşağıdaki işaretlemede gösterildiği gibi, TextBox, id Button ve Label Web denetimleri için HTML öğelerinin değerleri, Web denetimlerinin değerleriyle ID sayfadaki adlandırma kapsayıcılarının değerlerinin bir bileşimidirID.

<p>
 Please enter your age:
 <input name="ctl00$MainContent$Age" type="text" size="3" id="ctl00_MainContent_Age" />
</p>
<p>

 <input type="submit" name="ctl00$MainContent$SubmitButton" value="Submit" id="ctl00_MainContent_SubmitButton" />
</p>
<p>
 <span id="ctl00_MainContent_Results"></span>
</p>

Bu öğreticide daha önce belirtildiği gibi, hem ana sayfa hem de ContentPlaceHolders adlandırma kapsayıcıları olarak hizmet verir. Sonuç olarak, her ikisi de iç içe denetimlerinin işlenmiş ID değerlerine katkıda bulunur. TextBox özniteliğini id alın, örneğin: ctl00_MainContent_Age. TextBox denetiminin değerinin ID olduğunu Agehatırlayın. Bu, ContentPlaceHolder denetiminin ID değeri olan ön MainContentekini alır. Ayrıca, bu değer ana sayfanın ID değeri ctl00olan ön ekini alır. Net etkisi, ana sayfanın, ContentPlaceHolder denetiminin ve TextBox'ın kendisinden oluşan ID bir id öznitelik değeridir.

Şekil 4'de bu davranış gösterilmektedir. TextBox'ın Age işlendiğini id belirlemek için TextBox denetiminin ID Agedeğeriyle başlayın. Ardından, denetim hiyerarşisini yukarı doğru çalışın. Her adlandırma kapsayıcısında (şeftali rengine sahip düğümler), işlenen id geçerlinin önüne adlandırma kapsayıcısının idön ekini koyun.

İşlenen Kimlik Öznitelikleri Adlandırma Kapsayıcılarının Kimlik Değerlerini Temel Alır

Şekil 04: İşlenen id Öznitelikler Adlandırma Kapsayıcılarının Değerlerine Dayanır ID

Not

Ele aldığımız gibi, ctl00 işlenen id özniteliğin bölümü ana sayfanın değerini oluşturur ID , ancak bu ID değerin nasıl ortaya geldiğini merak ediyor olabilirsiniz. Ana sayfamızda veya içerik sayfamızda herhangi bir yerde belirtmedik. ASP.NET sayfasındaki çoğu sunucu denetimi, sayfanın bildirim temelli işaretlemesi aracılığıyla açıkça eklenir. MainContent ContentPlaceHolder denetimi, işaretlemesinde Site.masteraçıkça belirtildi; Age TextBox'ın işaretlemesi tanımlandıIDIssues.aspx. Bu denetim türlerinin ID değerlerini Özellikler penceresi veya bildirim temelli söz diziminden belirtebiliriz. Ana sayfanın kendisi gibi diğer denetimler bildirim temelli işaretlemede tanımlanmaz. Sonuç olarak, değerleri ID bizim için otomatik olarak oluşturulmalıdır. ASP.NET altyapısı, kimlikleri açıkça ayarlanmamış denetimler için çalışma zamanındaki değerleri ayarlar ID . Adlandırma desenini ctlXXkullanır; burada XX sıralı olarak artan bir tamsayı değeridir.

Ana sayfanın kendisi bir adlandırma kapsayıcısı görevi üstlendiği için, ana sayfada tanımlanan Web denetimleri de işlenmiş öznitelik değerlerini değiştirmiş id olur. Örneğin, DisplayDate Ana Sayfalarla Site Genelinde Düzen Oluşturma öğreticisinde ana sayfaya eklediğimiz Etiket aşağıdaki işlenmiş işaretlemeye sahiptir:

<span id="ctl00_DateDisplay">current date</span>

Özniteliğin id hem ana sayfanın ID değerini (ctl00) hem de ID Label Web denetiminin (DateDisplay) değerini içerdiğini unutmayın.

3. Adım: Program Aracılığıyla Web Denetimlerine BaşvurmaFindControl

Her ASP.NET sunucu denetimi, denetimin alt öğelerinde controlID adlı bir denetim arayan bir yöntem içerirFindControl("controlID"). Böyle bir denetim bulunursa döndürülür; eşleşen bir denetim bulunamazsa döndürür FindControl Nothing.

FindControl bir denetime erişmeniz gereken ancak doğrudan başvurunuz olmayan senaryolarda kullanışlıdır. Örneğin GridView gibi veri Web denetimleriyle çalışırken GridView'un alanlarındaki denetimler bildirim temelli söz diziminde bir kez tanımlanır, ancak çalışma zamanında her GridView satırı için denetimin bir örneği oluşturulur. Sonuç olarak, çalışma zamanında oluşturulan denetimler var, ancak arka planda kod sınıfından doğrudan başvuru yok. Sonuç olarak, GridView'un alanları içinde belirli bir denetimle program aracılığıyla çalışmak için kullanmamız FindControl gerekir. (Veri Web denetiminin şablonlarındaki denetimlere erişmek için kullanma FindControl hakkında daha fazla bilgi için bkz. Verilere Dayalı Özel Biçimlendirme.) Bu senaryo, Dinamik Veri Girişi Kullanıcı Arabirimleri Oluşturma başlığında ele alınan bir konu olan Web Formu'na dinamik olarak Web denetimleri eklerken de oluşur.

bir içerik sayfasındaki denetimleri aramak için yönteminin kullanılmasını FindControl göstermek için, 'nin Click olayı için SubmitButtonbir olay işleyicisi oluşturun. Olay işleyicisinde aşağıdaki kodu ekleyin. Bu kod, yöntemini kullanarak FindControl TextBox ve Results Label'a program aracılığıyla başvurur Age ve ardından kullanıcının girişlerine göre içinde Results bir ileti görüntüler.

Not

Elbette, bu örnekte Label ve TextBox denetimlerine başvurmak için kullanmamız FindControl gerekmez. Bunlara doğrudan özellik değerleri aracılığıyla ID başvurabiliriz. İçerik sayfasından kullanırken FindControl neler olduğunu göstermek için burayı kullanıyorumFindControl.

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 Dim ResultsLabel As Label = CType(FindControl("Results"), Label)
 Dim AgeTextBox As TextBox = CType(Page.FindControl("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

yöntemini çağırmak FindControl için kullanılan söz dizimi ilk iki satırda SubmitButton_Clickbiraz farklılık gösterse de, bunlar eşanlamlı olarak eşdeğerdir. Tüm ASP.NET sunucu denetimlerinin bir FindControl yöntem içerdiğini hatırlayın. Bu, tüm ASP.NET arka planda kod sınıflarının türetilmiş olması gereken sınıfı içerir Page . Bu nedenle, arka planda kod sınıfınızda veya özel bir temel sınıfta yöntemini geçersiz kılmadığınız FindControl varsayılarak çağrısı FindControl("controlID") ile Page.FindControl("controlID")eşdeğerdir.

Bu kodu girdikten sonra tarayıcı üzerinden sayfayı IDIssues.aspx ziyaret edin, yaşınızı girin ve "Gönder" düğmesine tıklayın. "Gönder" düğmesine tıklandığında bir NullReferenceException oluşturulur (bkz. Şekil 5).

NullReferenceException Tetikleniyor

Şekil 05: A NullReferenceException Yükseltilmiş (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Olay işleyicisinde bir kesme noktası ayarlarsanız, her iki çağrının SubmitButton_Click FindControl da döndürdüğünü Nothinggörürsünüz. NullReferenceException, TextBox'ın Text özelliğine erişmeye Age çalışırken oluşturulur.

Sorun, Control.FindControl yalnızca Aynı adlandırma kapsayıcısında bulunan Denetimin alt öğelerini aramadır. Ana sayfa yeni bir adlandırma kapsayıcısı oluşturduğundan, ana sayfa nesnesine ctl00hiçbir zaman geçirilmeme Page.FindControl("controlID") çağrısı yapılır. (Nesneyi ana sayfa ctl00nesnesinin üst öğesi olarak gösteren denetim hiyerarşisini Page görüntülemek için Şekil 4'e geri bakın.) Bu nedenle, Results Label ve Age TextBox bulunmaz ve AgeTextBox ResultsLabel değerlerine Nothingatanır.

Bu sınamanın iki geçici çözümü vardır: uygun denetime bir kerede bir adlandırma kapsayıcısı olmak üzere detaya gidebiliriz; veya adlandırma kapsayıcılarını kullanan kendi FindControl yöntemimizi oluşturabiliriz. Şimdi bu seçeneklerin her birini inceleyelim.

Uygun Adlandırma Kapsayıcısında Detaya Gitme

Label veya Age TextBox'a başvurmak Results için kullanmak FindControl için aynı adlandırma kapsayıcısında bir ata denetiminden çağrı FindControl yapmamız gerekir. Şekil 4'ün gösterdiği gibi ContentPlaceHolder MainContent denetimi, aynı adlandırma kapsayıcısının içindeki veya Age öğesinin tek atasıdırResults. Başka bir deyişle, aşağıdaki kod parçacığında gösterildiği gibi denetimden MainContent yöntemini çağırmakFindControl, veya Age denetimlerine Results doğru bir başvuru döndürür.

Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

Ancak, ContentPlaceHolder ana sayfada tanımlandığından yukarıdaki söz dizimini kullanarak içerik sayfamızın arka kod sınıfındaki ContentPlaceHolder ile MainContent çalışamıyoruz. Bunun yerine, öğesine bir başvuru almak için MainContentkullanmalıyızFindControl. Olay işleyicisindeki SubmitButton_Click kodu aşağıdaki değişikliklerle değiştirin:

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 Dim MainContent As ContentPlaceHolder = CType(FindControl("MainContent"), ContentPlaceHolder)

 Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
 Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

Sayfayı bir tarayıcı üzerinden ziyaret ederseniz yaşınızı girin ve "Gönder" düğmesine tıklarsanız, bir NullReferenceException yükseltilir. Olay işleyicisinde SubmitButton_Click bir kesme noktası ayarlarsanız, nesnenin FindControl yöntemini çağırmaya çalışırken bu özel durumun oluştuğunı MainContent görürsünüz. MainContent yöntemi "MainContent" adlı bir nesneyi bulamadığından FindControl nesnesi eşittirNothing. Temeldeki neden Label ve Age TextBox denetimleriyle Results aynıdır: FindControl aramasını denetim hiyerarşisinin en üstünden başlatır ve adlandırma kapsayıcılarına nüfuz etmez, ancak MainContent ContentPlaceHolder bir adlandırma kapsayıcısı olan ana sayfanın içindedir.

'a başvuru almak için kullanabilmemiz FindControl için MainContentönce ana sayfa denetimine bir başvuru yapmamız gerekir. Ana sayfaya bir başvurumuz olduğunda, ContentPlaceHolder'a MainContent FindControl ve buradan Label ve Age TextBox'a Results başvurular (yine kullanarakFindControl) ile bir başvuru alacağız. Peki ana sayfaya nasıl başvuru alacağız? İşlenen işaretlemedeki öznitelikleri inceleyerek id , ana sayfanın ID değerinin olduğu ctl00açıktır. Bu nedenle, ana sayfaya bir başvuru almak için kullanabilir, sonra bu nesneyi kullanarak öğesine başvuru MainContentalabilir ve bu şekilde devam edebilirizPage.FindControl("ctl00"). Aşağıdaki kod parçacığında bu mantık gösterilmektedir:

'Get a reference to the master page
Dim ctl00 As MasterPage = CType(FindControl("ctl00"), MasterPage)

'Get a reference to the ContentPlaceHolder
Dim MainContent As ContentPlaceHolder = CType(ctl00.FindControl("MainContent"), ContentPlaceHolder)

'Reference the Label and TextBox controls
Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

Bu kod kesinlikle işe yarasa da, ana sayfanın otomatik olarak oluşturulan ID her zaman olacağını ctl00varsayar. Otomatik olarak oluşturulan değerler hakkında varsayımlarda bulunmak hiçbir zaman iyi bir fikir olmaz.

Neyse ki, ana sayfa başvurusuna sınıfın Page Master özelliği aracılığıyla erişilebilir. Bu nedenle, ContentPlaceHolder'a erişmek MainContent için ana sayfaya başvuru almak için kullanmak FindControl("ctl00") zorunda kalmak yerine kullanabilirizPage.Master.FindControl("MainContent"). Olay işleyicisini SubmitButton_Click aşağıdaki kodla güncelleştirin:

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 'Get a reference to the ContentPlaceHolder
 Dim MainContent As ContentPlaceHolder = CType(Page.Master.FindControl("MainContent"), ContentPlaceHolder)

 'Reference the Label and TextBox controls
 Dim ResultsLabel As Label = CType(MainContent.FindControl("Results"), Label)
 Dim AgeTextBox As TextBox = CType(MainContent.FindControl("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

Bu kez, sayfayı bir tarayıcı üzerinden ziyaret ederek yaşınızı girin ve "Gönder" düğmesine tıkladıktan sonra, iletiyi etikette Results beklendiği gibi görüntüler.

Kullanıcının Yaşı Etikette Görüntülenir

Şekil 06: Kullanıcının Yaşı Etikette Görüntüleniyor (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Adlandırma Kapsayıcıları Aracılığıyla Özyinelemeli Arama

Önceki kod örneğinin ana sayfadan MainContent ContentPlaceHolder denetimine başvurmasının ve ardından Results 'den MainContentLabel ve Age TextBox denetimlerinin nedeni, yöntemin Control.FindControl yalnızca Control'ün adlandırma kapsayıcısında aramalar olmasıdır. FindControl İki farklı adlandırma kapsayıcısı içindeki iki denetim aynı ID değerlere sahip olabileceğinden, çoğu senaryoda adlandırma kapsayıcısının içinde kalmak mantıklıdır. TemplateField'lerinden birinde adlı ProductName bir Etiket Web denetimi tanımlayan bir GridView örneğini düşünün. Veriler çalışma zamanında GridView'a bağlandığında, her GridView satırı için bir ProductName Etiket oluşturulur. Tüm adlandırma kapsayıcıları arasında arama yapılıp çağrıldıysa FindControl Page.FindControl("ProductName")hangi Etiket örneği döndürülmelidir FindControl ? ProductName İlk GridView satırındaki Etiket mi? Son sıradaki mi?

Bu nedenle çoğu durumda yalnızca Control'ün adlandırma kapsayıcısında arama yapmak Control.FindControl mantıklıdır. Ancak, tüm adlandırma kapsayıcılarında benzersiz ID bir öğeye sahip olduğumuz ve denetime erişmek için denetim hiyerarşisindeki her adlandırma kapsayıcısına titizlikle başvurmak zorunda kalmamak istediğimiz, bize bakan örnek gibi başka durumlar da vardır. Yinelemeli olarak tüm adlandırma kapsayıcılarında arama yapan bir FindControl değişkene sahip olmak da mantıklıdır. Ne yazık ki, .NET Framework böyle bir yöntem içermez.

İyi haber, tüm adlandırma kapsayıcılarını özyinelemeli olarak arayan kendi FindControl yöntemimizi oluşturabilmektir. Aslında, uzantı yöntemlerini kullanarak mevcut FindControl yöntemine eşlik etmek için sınıfına Control bir FindControlRecursive yönteme dokunabiliriz.

Not

Uzantı yöntemleri, .NET Framework sürüm 3.5 ve Visual Studio 2008 ile birlikte gelen diller olan C# 3.0 ve Visual Basic 9'da yeni bir özelliktir. Kısacası, uzantı yöntemleri bir geliştiricinin özel bir söz dizimi aracılığıyla mevcut bir sınıf türü için yeni bir yöntem oluşturmasına olanak sağlar. Bu yararlı özellik hakkında daha fazla bilgi için, Uzantı Yöntemleriyle Temel Tür İşlevselliğini Genişletme makaleme bakın.

Uzantı yöntemini oluşturmak için adlı PageExtensionMethods.vbklasöre App_Code yeni bir dosya ekleyin. adlı FindControlRecursive bir uzantı yöntemi ekleyin ve adlı parametreyi String controlIDgirdi olarak alır. Uzantı yöntemlerinin düzgün çalışması için sınıfın olarak Module işaretlenmesi ve uzantı yöntemlerinin özniteliğine <Extension()> ön eklenmesi çok önemlidir. Ayrıca, tüm uzantı yöntemleri, uzantı yönteminin uygulandığı türde bir nesneyi ilk parametre olarak kabul etmelidir.

Bunu Module ve uzantı yöntemini tanımlamak için dosyaya FindControlRecursive aşağıdaki kodu PageExtensionMethods.vb ekleyin:

Imports System.Runtime.CompilerServices

Public Module PageExtensionMethods
 <Extension()> _
  Public Function FindControlRecursive(ByVal ctrl As Control, ByVal controlID As String) As Control
 If String.Compare(ctrl.ID, controlID, True) = 0 Then
 ' We found the control!
 Return ctrl
 Else
 ' Recurse through ctrl's Controls collections
 For Each child As Control In ctrl.Controls
 Dim lookFor As Control = FindControlRecursive(child, controlID)

 If lookFor IsNot Nothing Then
 Return lookFor  ' We found the control
 End If
 Next

 ' If we reach here, control was not found
 Return Nothing
 End If
 End Function
End Module

Bu kod mevcut olduğunda, sayfanın arka planda kod sınıfına IDIssues.aspx dönün ve geçerli FindControl yöntem çağrılarına açıklama ekleyin. bunları çağrısıyla Page.FindControlRecursive("controlID")değiştirin. Uzantı yöntemlerinin en iyi özelliği, doğrudan IntelliSense açılan listelerinde görünmeleridir. Şekil 7'de gösterildiği gibi, yazıp Page nokta tuşuna bastığınızda, FindControlRecursive yöntem diğer Control sınıf yöntemleriyle birlikte IntelliSense açılan menüsüne eklenir.

Uzantı Yöntemleri IntelliSense Açılan Listelerine Dahil Edilir

Şekil 07: Uzantı Yöntemleri IntelliSense Açılan Listelerine Dahil Edilir (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Olay işleyicisine SubmitButton_Click aşağıdaki kodu girin ve ardından sayfayı ziyaret edip yaşınızı girip "Gönder" düğmesine tıklayarak kodu test edin. Şekil 6'da gösterildiği gibi, sonuçta elde edilen çıkış "Yaşınız geçti!" iletisi olacaktır.

Protected Sub SubmitButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubmitButton.Click
 Dim ResultsLabel As Label = CType(Page.FindControlRecursive("Results"), Label)
 Dim AgeTextBox As TextBox = CType(Page.FindControlRecursive("Age"), TextBox)

 ResultsLabel.Text = String.Format("You are {0} years old!", AgeTextBox.Text)
End Sub

Not

Uzantı yöntemleri C# 3.0 ve Visual Basic 9'da yeni olduğundan, Visual Studio 2005 kullanıyorsanız uzantı yöntemlerini kullanamazsınız. Bunun yerine yöntemini bir yardımcı sınıfında uygulamanız FindControlRecursive gerekir. Rick Strahl, Maser Pages ve FindControlASP.NET blog gönderisinde böyle bir örnekle karşılandı.

4. Adım: İstemci Tarafı Betiğinde DoğruidÖznitelik Değerini Kullanma

Bu öğreticinin girişinde belirtildiği gibi, bir Web denetiminin işlenen id özniteliği genellikle istemci tarafı betiğinde belirli bir HTML öğesine program aracılığıyla başvurmak için kullanılır. Örneğin, aşağıdaki JavaScript bir HTML öğesine kendi id tarafından başvurur ve değerini kalıcı bir ileti kutusunda görüntüler:

var elem = document.getElementById("Age");
if (elem != null)
    alert("You entered " + elem.value + " into the Age text box.");

Adlandırma kapsayıcısı içermeyen ASP.NET sayfalarda, işlenen HTML öğesinin id özniteliğinin Web denetiminin ID özellik değeriyle aynı olduğunu hatırlayın. Bu nedenle, öznitelik değerlerinde JavaScript koduna id sabit kod almak caziptir. Diğer bir ifadeyle, TextBox Web denetimine istemci tarafı betiği aracılığıyla erişmek Age istediğinizi biliyorsanız, bunu çağrısı document.getElementById("Age")yoluyla yapın.

Bu yaklaşımdaki sorun, ana sayfaları (veya diğer adlandırma kapsayıcısı denetimlerini) kullanırken işlenen HTML'nin id ID Web denetiminin özelliğiyle eş anlamlı olmamasıdır. İlk eğiliminiz, bir tarayıcı üzerinden sayfayı ziyaret etmek ve gerçek id özniteliği belirlemek için kaynağı görüntülemek olabilir. İşlenen id değeri bildiğinizde, istemci tarafı betiği aracılığıyla birlikte çalışmanız gereken HTML öğesine erişmek için getElementById çağrısına yapıştırabilirsiniz. Sayfanın denetim hiyerarşisinde yapılan bazı değişiklikler veya adlandırma denetimlerinin özelliklerindeki değişiklikler ID sonuçta id elde edilen özniteliği değiştirip JavaScript kodunuzu bozacağından bu yaklaşım idealden daha düşüktür.

İyi haber, id işlenen öznitelik değerinin Web denetiminin ClientID özelliği aracılığıyla sunucu tarafı kodda erişilebilir olmasıdır. İstemci tarafı betiğinde id kullanılan öznitelik değerini belirlemek için bu özelliği kullanmanız gerekir. Örneğin, çağrıldığında TextBox değerini Age kalıcı bir ileti kutusunda görüntüleyen sayfaya bir JavaScript işlevi eklemek için olay işleyicisine Page_Load aşağıdaki kodu ekleyin:

ClientScript.RegisterClientScriptBlock(Me.GetType(), "ShowAgeTextBoxScript", _
 "function ShowAge() " & vbCrLf & _
 "{" & vbCrLf & _
 " var elem = document.getElementById('" & AgeTextBox.ClientID & "');" & vbCrLf & _
 " if (elem != null)" & vbCrLf & _
 " alert('You entered ' + elem.value + ' into the Age text box.');" & vbCrLf & _
 "}", True)

Yukarıdaki kod, TextBox özelliğinin Age değerini JavaScript çağrısına eklergetElementById.ClientID Bu sayfayı bir tarayıcı üzerinden ziyaret edip HTML kaynağını görüntülerseniz aşağıdaki JavaScript kodunu bulursunuz:

<script type="text/javascript">
//<![CDATA[
function ShowAge()
{
 var elem = document.getElementById('ctl00_MainContent_Age');
 if (elem != null)
 alert('You entered ' + elem.value + ' into the Age text box.');
}//]]>
</script>

doğru id öznitelik değerinin çağrısı ctl00_MainContent_Ageiçinde nasıl göründüğüne getElementByIddikkat edin. Bu değer çalışma zamanında hesaplandığından, sayfa denetimi hiyerarşisinde daha sonra yapılan değişikliklerden bağımsız olarak çalışır.

Not

Bu JavaScript örneği yalnızca bir sunucu denetimi tarafından işlenen HTML öğesine doğru başvuruda bulunan bir JavaScript işlevinin nasıl ekleneceğini gösterir. Bu işlevi kullanmak için, belge yüklendiğinde veya belirli bir kullanıcı eylemi devre dışı olduğunda işlevi çağırmak için ek JavaScript yazmanız gerekir. Bu ve ilgili konular hakkında daha fazla bilgi için İstemci Tarafı Betiği ile Çalışma konusuna bakın.

Özet

Bazı ASP.NET sunucu denetimleri, alt denetimlerinin işlenen id öznitelik değerlerini ve yöntemi tarafından FindControl tuvallenen denetimlerin kapsamını etkileyen adlandırma kapsayıcıları görevi görür. Ana sayfalarla ilgili olarak, hem ana sayfanın kendisi hem de ContentPlaceHolder denetimleri kapsayıcıları adlandırır. Sonuç olarak, kullanarak FindControliçerik sayfasındaki denetimlere program aracılığıyla başvurmak için biraz daha fazla çalışma yapmamız gerekir. Bu öğreticide iki tekniği inceledik: ContentPlaceHolder denetiminde detaya gitme ve yöntemini çağırma FindControl ve tüm adlandırma kapsayıcılarında özyinelemeli olarak arama yapan kendi FindControl uygulamamızı döndürme.

Web denetimlerine başvurmayla ilgili olarak kapsayıcıları adlandırmaya yönelik sunucu tarafı sorunlarına ek olarak, istemci tarafı sorunları da vardır. Adlandırma kapsayıcıları olmadığında, Web denetiminin ID özellik değeri ve işlenen id öznitelik değeri aynı olur. Ancak adlandırma kapsayıcısının eklenmesiyle, işlenen id öznitelik hem Web denetiminin değerlerini hem de ID denetim hiyerarşisinin üst öğesindeki adlandırma kapsayıcılarını içerir. Bu adlandırma endişeleri, istemci tarafı betiğinizde işlenen id öznitelik değerini belirlemek için Web denetiminin ClientID özelliğini kullandığınız sürece sorun değildir.

Mutlu Programlama!

Daha Fazla Bilgi

Bu öğreticide ele alınan konular hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:

Yazar hakkında

Birden çok ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışır. Son kitabı Sams Teach Yourself ASP.NET 3.5 in 24 Hours. Scott'a adresinden mitchell@4GuysFromRolla.com veya adresinden blogu http://ScottOnWriting.NETaracılığıyla ulaşılabilir.

Özel Teşekkürler

Bu öğretici serisi birçok yararlı gözden geçiren tarafından gözden geçirildi. Bu öğreticinin baş gözden geçirenleri Zack Jones ve Suchi Barnerjee'ydi. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, bana adresine mitchell@4GuysFromRolla.combir satır bırakın.