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

Scott Mitchell tarafından

Kodu indirin veya PDF 'yi indirin

ContentPlaceHolder denetimlerinin adlandırma kapsayıcısı olarak nasıl çalıştığını gösterir ve bu nedenle programlı olarak bir denetim ile çalışır (FindControl aracılığıyla). Bu soruna ve geçici çözümlere bakar. Ayrıca, elde edilen ClientID değerine programlı olarak nasıl erişebileceğinizi açıklar.

Giriş

Tüm ASP.NET Server denetimleri, denetimi benzersiz bir şekilde tanımlayan bir ID özelliği içerir ve denetimin arka plan kod sınıfında programlı olarak eriştiği anlamına gelir. Benzer şekilde, bir HTML belgesindeki öğeler, öğeyi benzersiz bir şekilde tanımlayan bir id özniteliği içerebilir; Bu id değerler genellikle belirli bir HTML öğesine programlı olarak başvurmak için istemci tarafı betikte kullanılır. Bu şekilde, bir ASP.NET sunucu denetimi HTML 'de işlendiğinde, ID değerinin işlenmiş HTML öğesinin id değeri olarak kullanıldığını varsayabilirsiniz. Bu durum, belirli koşullarda tek bir ID değeri olan tek bir denetimin, işlenmiş biçimlendirmede birden çok kez görünebileceğinden, bu durum değildir. ProductName``ID bir değeri olan bir etiket Web denetimiyle TemplateField içeren bir GridView denetimi düşünün. GridView, çalışma zamanında veri kaynağına bağlandığında, bu etiket her GridView satırı için yinelenir. İşlenen her etiketin benzersiz bir id değeri olması gerekir.

Bu tür senaryoları işlemek için, ASP.NET, belirli denetimlerin adlandırma kapsayıcıları olarak kullanılmasına izin verir. Adlandırma kapsayıcısı yeni bir ID ad alanı işlevi görür. Adlandırma kapsayıcısı içinde görünen tüm sunucu denetimleri, adlandırma kapsayıcısı denetiminin ID önekli id değerine sahiptir. Örneğin, GridView ve GridViewRow sınıfları, her iki adlandırma kapsayıcılarıdır. Sonuç olarak, ID ProductName olan bir GridView TemplateField 'da tanımlanan bir etiket denetimine GridViewID_GridViewRowID_ProductNameişlenmiş id değeri verilir. Gridviewrowıd her GridView satırı için benzersiz olduğundan, sonuçta elde edilen id değerleri benzersizdir.

Note

INamingContainer arabirimi , belirli bir ASP.NET Server denetiminin bir adlandırma kapsayıcısı olarak çalışması gerektiğini belirtmek için kullanılır. INamingContainer arabirimi, sunucu denetiminin uygulaması gereken herhangi bir yöntemi değil; Bunun yerine işaret olarak kullanılır. İşlenmiş biçimlendirmeyi oluştururken, bir denetim bu arabirimi uygularsa, ASP.NET altyapısı ID değerini otomatik olarak alt öğelerinden ' işlenmiş id öznitelik değerlerine ekler. Bu işlem, adım 2 ' de daha ayrıntılı bir şekilde ele alınmıştır.

Adlandırma kapsayıcıları yalnızca işlenen id öznitelik değerini değiştirmez, ancak aynı zamanda denetimin ASP.NET sayfasının arka plan kod sınıfından programlama yoluyla nasıl başvurduğunu da etkiler. FindControl("controlID") yöntemi, yaygın olarak bir Web denetimine başvurmak için kullanılır. Ancak FindControl, adlandırma kapsayıcıları aracılığıyla sızmaz. Sonuç olarak, GridView veya diğer adlandırma kapsayıcısı içindeki denetimlere başvurmak için Page.FindControl yöntemini doğrudan kullanamazsınız.

Yukarıda da belirtildiği gibi, ana sayfalar ve Contentyertutucuların her ikisi de adlandırma kapsayıcıları olarak uygulanır. Bu öğreticide, ana sayfaların HTML öğesi id nasıl etkilediğini ve FindControlkullanarak bir içerik sayfasında program aracılığıyla Web denetimlerine nasıl başvurulacağını inceleyeceğiz.

1. Adım: yeni bir 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 IDIssues.aspx adlı yeni bir içerik sayfası oluşturun ve Site.master ana sayfasına bağlama.

Idissues. aspx Içerik sayfasını kök klasöre ekleyin

Şekil 01: içerik sayfası IDIssues.aspx kök klasöre ekleyin

Visual Studio, ana sayfanın dört Contentiyertutucusu için otomatik olarak bir Içerik denetimi oluşturur. Birden çok Contenttutucuları ve varsayılan içerik öğreticisinde belirtildiği gibi, içerik denetimi yoksa, ana sayfanın varsayılan ContentPlaceHolder içeriği yayılır. QuickLoginUI ve LeftColumnContent Contentyertutucuları Bu sayfa için uygun varsayılan biçimlendirmeyi içerdiğinden, devam edin ve ilgili Içerik denetimlerini IDIssues.aspxkaldırın. Bu noktada, içerik sayfasının bildirim temelli biçimlendirme 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 sayfada başlık, meta etiketler ve DIĞER HTML üst bilgilerini belirtme öğreticisinde, açıkça ayarlanmamışsa sayfanın başlığını otomatik olarak yapılandıran özel bir temel sayfa sınıfı (BasePage) oluşturduk. IDIssues.aspx sayfasında bu işlevselliği kullanmak için, sayfanın arka plan kod sınıfı BasePage sınıfından türetmelidir (System.Web.UI.Pageyerine). Arka plan kod sınıfının tanımını, aşağıdakine benzer şekilde değiştirin:

Partial Class IDIssues
 Inherits BasePage

End Class

Son olarak, Web.sitemap dosyasını bu yeni ders için bir giriş içerecek şekilde güncelleştirin. <siteMapNode> bir öğesi ekleyin ve title ve url özniteliklerini sırasıyla "Denetim KIMLIĞI adlandırma sorunları" ve ~/IDIssues.aspxolarak ayarlayın. Bunu yaptıktan sonra Web.sitemap dosyanızın biçimlendirmesi 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, Web.sitemap yeni site haritası girişi, sol sütundaki dersler bölümünde hemen yansıtılır.

Dersler bölümü artık "denetim KIMLIĞI adlandırma sorunlarına bir bağlantı Içerir"

Şekil 02: dersler bölümü artık "denetim kimliği adlandırma sorunları" bağlantısını içerir

2. Adım: IşlenmişIDdeğişikliklerini Inceleme

ASP.NET altyapısının, sunucu denetimlerinin işlenmiş id değerlerinde yaptığı değişiklikleri daha iyi anlamak için, IDIssues.aspx sayfasına birkaç Web denetimi ekleyelim ve sonra tarayıcıya gönderilen işlenmiş biçimlendirmeyi görüntüleyelim. Özellikle, "Lütfen yaşını girin:" ve ardından bir metin kutusu Web denetimi yazın. Sayfada daha fazla bir düğme web denetimi ve bir etiket Web denetimi ekleyin. TextBox 'ın ID ve Columns özelliklerini sırasıyla Age ve 3 olarak ayarlayın. Düğmenin Text ve ID özelliklerini "Gönder" ve SubmitButtonolarak ayarlayın. Etiketin Text özelliğini temizleyin ve ID Resultsolarak ayarlayın.

Bu noktada, Içerik denetiminizin bildirime dayalı biçimlendirmesi 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.

Sayfa üç Web denetimi Içerir: TextBox, Button ve Label

Şekil 03: sayfa üç Web denetimi içerir: bir TextBox, düğme ve etiket (tam boyutlu görüntüyü görüntülemek için tıklayın)

Sayfayı bir tarayıcıda ziyaret edin ve HTML kaynağını görüntüleyin. Aşağıdaki biçimlendirme gösterildiği gibi, TextBox, Button ve Label Web denetimlerinin HTML öğelerinin id değerleri, Web denetimlerinin ID değerlerinin ve sayfadaki adlandırma kapsayıcılarının ID değerlerinin bir birleşimidir.

<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 onun Içerik yer tutucuları adlandırma kapsayıcıları olarak görev yapar. Sonuç olarak, her ikisi de iç içe denetimlerinin işlenmiş ID değerlerini katkıda bulunur. TextBox 'ın id özniteliğini al, örneğin: ctl00_MainContent_Age. TextBox denetiminin ID değerinin Ageolduğunu hatırlayın. Bu, ContentPlaceHolder denetimin ID değeri MainContentön ekine sahiptir. Ayrıca, bu değere ana sayfanın ID değeri ctl00ön eki eklenir. Net etkisi, ana sayfanın ID değerlerini, ContentPlaceHolder denetimini ve metin kutusunun kendisini içeren bir id özniteliği değeridir.

Şekil 4 ' te bu davranış gösterilmektedir. Age TextBox 'ın işlenmiş id belirlenmesi için, AgeTextBox denetiminin ID değeri ile başlayın. Sonra, denetim hiyerarşisi için bir yöntem çalışın. Her adlandırma kapsayıcısında (açık rengi olan bu düğümler), adlandırma kapsayıcısının idgeçerli olarak işlenen id ön eki.

Işlenmiş kimlik öznitelikleri, adlandırma kapsayıcılarının KIMLIK değerlerine dayalıdır

Şekil 04: Işlenmiş id öznitelikleri, adlandırma kapsayıcılarının ID değerlerine dayalıdır

Note

Tartışıyoruz, işlenmiş id özniteliğinin ctl00 kısmı ana sayfanın ID değerini oluşturur, ancak bu ID değerin nasıl geldiğini merak ediyor olabilirsiniz. Ana veya içerik sayfamızda bir yere belirtmedik. Bir ASP.NET sayfasındaki çoğu sunucu denetimi, sayfanın bildirim temelli işaretlemesi aracılığıyla açıkça eklenir. MainContent ContentPlaceHolder denetimi, Site.masterbiçimlendirmesinde açıkça belirtilmiştir; Age metin kutusu IDIssues.aspxbiçimlendirmesi olarak tanımlandı. Bu denetim türlerinin ID değerlerini Özellikler penceresi veya bildirime dayalı sözdiziminden belirteceğiz. Ana sayfanın kendisi gibi diğer denetimler, bildirim temelli biçimlendirmede tanımlanmamıştır. Sonuç olarak, ID değerlerinin ABD için otomatik olarak oluşturulması gerekir. ASP.NET altyapısı, kimlikleri açıkça ayarlanmamış olan denetimler için çalışma zamanında ID değerlerini ayarlar. ctlXXadlandırma modelini kullanır, burada xx sıralı olarak artan tamsayı değeridir.

Ana sayfanın kendisi bir adlandırma kapsayıcısı olarak görev yaptığından, ana sayfada tanımlanan Web denetimleri, işlenen id öznitelik değerlerini de değiştirmiş. Örneğin, Ana sayfa Ile site genelinde düzen oluşturma öğreticisinde ana sayfaya eklediğimiz DisplayDate etiketi aşağıdaki işlenmiş biçimlendirmeye sahiptir:

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

id özniteliğinin hem ana sayfanın ID değerini (ctl00) hem de etiketin Web denetiminin ID değerini (DateDisplay) içerdiğini unutmayın.

3. Adım: program aracılığıyla Web denetimlerine başvurmaFindControl

Her ASP.NET sunucu denetimi, denetimin alt öğelerinden ControlIDadlı bir denetim için arama yapan bir FindControl("controlID") yöntemi içerir. Böyle bir denetim bulunursa, döndürülür; eşleşen bir denetim bulunamazsa, FindControl Nothingdöndürür.

FindControl, bir denetime erişmeniz gereken ancak kendisine doğrudan başvurmayan senaryolarda yararlıdır. GridView gibi veri Web denetimleriyle çalışırken, örneğin, GridView 'un alanlarındaki denetimler bildirim temelli sözdiziminde bir kez tanımlanır, ancak çalışma zamanında her GridView satırı için bir denetimin örneği oluşturulur. Sonuç olarak, çalışma zamanında oluşturulan denetimler mevcuttur, ancak arka plan kod sınıfından kullanılabilecek doğrudan bir başvuruya sahip değildir. Sonuç olarak, GridView 'un alanları içindeki belirli bir denetimle programlı bir şekilde çalışmak için FindControl kullanmanız gerekir. (Bir veri Web denetiminin şablonları içindeki denetimlere erişmek için FindControl kullanma hakkında daha fazla bilgi için, bkz. verileri temel alan özel biçimlendirme.) Bu senaryo, dinamik veri girişi kullanıcı arabirimleri oluşturmabölümünde ele alınan bir konu olan Web formuna dinamik olarak Web denetimleri eklerken meydana gelir.

Bir içerik sayfasında denetimleri aramak için FindControl yöntemini kullanmayı göstermek için, SubmitButton``Click olayı için bir olay işleyicisi oluşturun. Olay işleyicisinde, FindControl yöntemini kullanarak Age TextBox ve Results etiketine programlı olarak başvuran aşağıdaki kodu ekleyin ve ardından kullanıcının girişine göre Results bir ileti görüntüler.

Note

Tabii ki, bu örnek için etiket ve metin kutusu denetimlerine başvurmak üzere FindControl kullanmıyoruz. Bunlara ID özellik değerleri aracılığıyla doğrudan başvuracağız. Bir içerik sayfasından FindControl kullanırken ne olduğunu göstermek için FindControl burada kullanıyorum.

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

FindControl yöntemini çağırmak için kullanılan sözdizimi, SubmitButton_Clickilk iki satırda biraz farklı olsa da, anlamsal olarak eşdeğerdir. Tüm ASP.NET Server denetimlerinin bir FindControl yöntemi içerdiğini hatırlayın. Bu, tüm ASP.NET arka plan kod sınıflarının türetmesini gerektiren Page sınıfını içerir. Bu nedenle, FindControl("controlID") çağrısı Page.FindControl("controlID")çağırma ile eşdeğerdir, ancak arka plan kod sınıfında veya özel bir temel sınıfta FindControl yöntemini geçersiz kılmadığınız varsayılır.

Bu kodu girdikten sonra tarayıcıda IDIssues.aspx sayfasını ziyaret edin, yaşını girin ve "Gönder" düğmesine tıklayın. "Gönder" düğmesine tıklandıktan sonra bir NullReferenceException tetiklenir (bkz. Şekil 5).

Bir NullReferenceException tetiklenir

Şekil 05: bir NullReferenceException tetiklenir (tam boyutlu görüntüyü görüntülemek için tıklayın)

SubmitButton_Click olay işleyicisinde bir kesme noktası ayarlarsanız, FindControl Nothingdöndüren her iki çağrının de olduğunu görürsünüz. NullReferenceException, Age TextBox 'ın Text özelliğine erişmeye çalıştıklarında tetiklenir.

Sorun, yalnızca denetiminaynı adlandırma kapsayıcısında olan alt öğelerinden yalnızca arama Control.FindControl. Ana sayfa yeni bir adlandırma kapsayıcısı oluşturduğundan, Page.FindControl("controlID") bir çağrı ana sayfa nesnesinin ctl00hiçbir şekilde hiçbir şekilde hiçbir şekilde değildir. (Page nesnesini ana sayfa ctl00nesnesinin üst öğesi olarak gösteren denetim hiyerarşisini görüntülemek için Şekil 4 ' e geri dönün.) Bu nedenle, Results etiketi ve Age metin kutusu bulunamadı ve ResultsLabel ve AgeTextBox Nothingdeğerler atanır.

Bu zorluk için iki geçici çözüm vardır: aynı anda bir adlandırma kapsayıcısı, uygun denetime göre ayrıntıya gidebiliriz; ya da, ad kapsayıcılarını engelleyen kendi FindControl yöntemi oluşturuyoruz. Bu seçeneklerin her birini inceleyelim.

Uygun adlandırma kapsayıcısının detayına gitme

Results etiketine veya Age metin kutusuna başvurmak için FindControl kullanmak için, aynı adlandırma kapsayıcısında bir üst denetimden FindControl çağırdık. Şekil 4 ' te gösterildiği gibi, MainContent ContentPlaceHolder denetimi aynı adlandırma kapsayıcısı içindeki Results veya Age tek üst öğesi. Diğer bir deyişle, aşağıdaki kod parçacığında gösterildiği gibi, MainContent denetiminden FindControl yöntemini çağırmak, Results veya Age denetimlerine 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özdizimini kullanarak içerik sayfanızın arka plan kod sınıfından ContentPlaceHolder MainContent ile çalışıyoruz. Bunun yerine, MainContentbir başvuru almak için FindControl kullandık. SubmitButton_Click olay işleyicisindeki 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ı aracılığıyla ziyaret ederseniz, yaşını girip "Gönder" düğmesine tıkladığınızda bir NullReferenceException oluşturulur. SubmitButton_Click olay işleyicisinde bir kesme noktası ayarlarsanız, MainContent nesnesinin FindControl yöntemini çağırmaya çalışırken bu özel durumun oluştuğunu görürsünüz. FindControl yöntemi "MainContent" adlı bir nesne bulamadığından, MainContent nesnesi Nothing eşittir. Temel neden, Results etiketi ve Age metin kutusu denetimleriyle aynıdır: FindControl, arama denetimini denetim hiyerarşisinin en üstünden başlatır ve adlandırma kapsayıcılarını göstermez, ancak MainContent ContentPlaceHolder, bir adlandırma kapsayıcısı olan ana sayfa içindedir.

MainContentbir başvuru almak için FindControl kullanabilmeniz için önce ana sayfa denetimine bir başvuruya ihtiyacımız var. Ana sayfaya bir başvurduktan sonra, FindControl ile ContentPlaceHolder MainContent bir başvuru alabilir ve buradan, Results etiketine ve Age metin kutusuna (FindControlkullanarak) başvurur. Ancak ana sayfaya nasıl bir başvuru alırız? İşlenmiş biçimlendirmede id özniteliklerini inceleyerek ana sayfanın ID değerinin ctl00olması önerilir. Bu nedenle, ana sayfaya başvuru almak için Page.FindControl("ctl00") kullanabiliriz, sonra da MainContentbir başvuru almak için bu nesneyi kullanabilirsiniz. Aşağıdaki kod parçacığı bu mantığı göstermektedir:

'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 tamamen çalışacaktır, ana sayfanın otomatik olarak oluşturulan ID her zaman ctl00olacağını varsayar. Otomatik olarak oluşturulan değerler hakkında varsayımlar yapmak hiç iyi bir fikir değildir.

Neyse ki, ana sayfaya yapılan bir başvuruya Page sınıfının Master özelliği aracılığıyla erişilebilir. Bu nedenle, MainContent ContentPlaceHolder öğesine erişmek için ana sayfanın bir başvurusunu almak üzere FindControl("ctl00") kullanmak yerine Page.Master.FindControl("MainContent")de kullanabilirsiniz. SubmitButton_Click olay işleyicisini 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ı ile ziyaret ederek, yaşını girerek ve "Gönder" düğmesine tıklamak, Results etiketinde iletiyi beklenen şekilde 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ülenir (tam boyutlu görüntüyü görüntülemek için tıklayın)

Adlandırma kapsayıcılarında yinelemeli arama

Önceki kod örneğine, ana sayfadan MainContent ContentPlaceHolder denetimine başvuruldu ve sonra MainContentolan Results etiketi ve Age TextBox denetimleri, Control.FindControl yönteminin yalnızca denetiminadlandırma kapsayıcısı içinde arama yaptığından oluşur. İki farklı adlandırma kapsayıcılarındaki iki denetim aynı ID değerine sahip olabileceğinden, adlandırma kapsayıcısı içinde FindControl olması çoğu senaryo açısından anlamlı hale gelir. TemplateFields içinde ProductName adlı bir etiket Web denetimi tanımlayan bir GridView 'un durumunu göz önünde bulundurun. Veriler GridView 'a çalışma zamanında bağlandığında her GridView satırı için bir ProductName etiketi oluşturulur. FindControl tüm adlandırma kapsayıcılarında arama yaptıysanız ve Page.FindControl("ProductName")çağırdık, FindControl hangi etiket örneği döndürmelidir? İlk GridView satırındaki ProductName etiketi mi? Son satırdaki bir tane?

Control.FindControl arama yalnızca denetiminadlandırma kapsayıcısı çoğu durumda daha anlamlı hale gelir. Ancak, tüm adlandırma kapsayıcıları genelinde benzersiz bir ID olduğu ve bir denetime erişmek için denetim hiyerarşisindeki her adlandırma kapsayıcısına daha fazla başvuru yapmaktan kaçınmak isteyen, bizim gibi başka durumlar da vardır. Tüm adlandırma kapsayıcılarını özyinelemeli olarak arayan FindControl bir değişken olması çok anlamlı olur. Ne yazık ki .NET Framework böyle bir yöntemi içermez.

İyi haber, tüm adlandırma kapsayıcılarını özyinelemeli olarak arayan kendi FindControl yöntemi oluşturabileceğiz. Aslında, genişletme yöntemlerini kullanarak, var olan FindControl yöntemine eşlik etmek için Control sınıfına FindControlRecursive bir yöntemi üzerinde Raptiye yapabilirsiniz.

Note

Uzantı yöntemleri, 3,5 ve Visual Studio C# 2008 .NET Framework sürümü ile birlikte gelen diller Visual Basic 3,0 ve 9 ' a yeni bir özelliktir. Kısaca uzantı yöntemleri, bir geliştiricinin özel bir sözdizimi aracılığıyla mevcut bir sınıf türü için yeni bir yöntem oluşturmasına izin verir. Bu yardımcı özellik hakkında daha fazla bilgi için, uzantı yöntemleriyle temel tür Işlevselliğini genişleterekmakaleme bakın.

Uzantı yöntemini oluşturmak için, PageExtensionMethods.vbadlı App_Code klasöre yeni bir dosya ekleyin. controlIDadlı bir String parametresi girişi olarak alan FindControlRecursive adlı bir uzantı yöntemi ekleyin. Uzantı yöntemlerinin düzgün çalışması için, sınıfın bir Module olarak işaretlenmesi ve genişletme yöntemlerinin <Extension()> özniteliğiyle ön eki olması çok önemlidir. Üstelik, tüm genişletme yöntemleri, ilk parametresi olarak Uzantı yönteminin uygulandığı türün bir nesnesi olarak kabul etmelidir.

Bu Module ve FindControlRecursive uzantısı yöntemini tanımlamak için aşağıdaki kodu PageExtensionMethods.vb dosyasına 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 kodla birlikte IDIssues.aspx sayfanın arka plan kod sınıfına dönün ve geçerli FindControl yöntemi çağrılarını not edin. Bunları Page.FindControlRecursive("controlID")çağrılarıyla değiştirin. Uzantı yöntemleriyle ilgili yenilikler, doğrudan IntelliSense açılan listelerinde görünürler. Şekil 7 ' de gösterildiği gibi, Page yazdığınızda ve sonra da nokta tuşuna bastığınızda, FindControlRecursive yöntemi diğer Control sınıfı yöntemleriyle birlikte IntelliSense açılır.

uzantısı yöntemleri, IntelliSense açılır listeleri 'ne dahildir

Şekil 07: uzantı yöntemleri, IntelliSense açılan listeleri 'ne dahildir (tam boyutlu görüntüyü görüntülemek için tıklayın)

SubmitButton_Click olay işleyicisine aşağıdaki kodu girin ve ardından sayfayı ziyaret ederek, yaşınızı girerek ve "Gönder" düğmesine tıklayarak test edin. Şekil 6 ' da gösterildiği gibi, sonuçta elde edilen çıktı, "yaş yıllardır!" 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

Note

Uzantı yöntemleri C# 3,0 ve Visual Basic 9 ' a yeni olduklarından, Visual Studio 2005 kullanıyorsanız uzantı yöntemlerini kullanamazsınız. Bunun yerine, FindControlRecursive yöntemini bir yardımcı sınıfında uygulamanız gerekir. Rick Strahl , blog gönderisine, ASP.net Maser sayfalarına ve FindControlbir örnektir.

4. Adım: Istemci tarafı betikte doğruidöznitelik değerini kullanma

Bu öğreticinin giriş bölümünde belirtildiği gibi, bir Web denetiminin işlenmiş id özniteliği, belirli bir HTML öğesine programlı bir şekilde başvurmak için istemci tarafı betikte kullanılan kullanım zamanıdır. Örneğin, aşağıdaki JavaScript id bir HTML öğesine başvurur ve sonra değerini bir kalıcı ileti kutusunda görüntüler:

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

ASP.NET sayfalarında bir adlandırma kapsayıcısı içermeyen, işlenmiş HTML öğesinin id özniteliği Web denetiminin ID Özellik değeri ile aynı olduğunu hatırlayın. Bu nedenle, id öznitelik değerleri ile JavaScript koduna sabit koda sahiptir. Diğer bir deyişle, Age metin kutusu Web denetimine istemci tarafı komut dosyası aracılığıyla erişmek istediğinizi biliyorsanız, bunu document.getElementById("Age")çağrısı aracılığıyla yapın.

Bu yaklaşımda sorun, ana sayfalar (veya diğer adlandırma kapsayıcı denetimleri) kullanılırken, işlenmiş HTML id Web denetiminin ID özelliği ile eş anlamlı olmadığı bir sorundur. İlk eğim, sayfayı bir tarayıcı aracılığıyla ziyaret edip gerçek id özniteliğini belirleyecek kaynağı görüntüleyebiliriz. İşlenmiş id değerini öğrendikten sonra, istemci tarafı komut dosyası aracılığıyla birlikte çalışmanız gereken HTML öğesine erişmek için getElementById çağrısına yapıştırabilirsiniz. Bu yaklaşım ideal olandan daha küçüktür çünkü sayfanın denetim hiyerarşisinde veya adlandırma denetimlerinin ID özelliklerinde yapılan değişiklikler, elde edilen id özniteliğini değiştirecek ve böylece JavaScript kodunuzu bozacaktır.

İyi haber, işlenen id öznitelik değerinin Web denetiminin ClientID özelliğiaracılığıyla sunucu tarafı kodda erişilebilir olması. İstemci tarafı betikte kullanılan id öznitelik değerini öğrenmek için bu özelliği kullanmanız gerekir. Örneğin, bu sayfaya bir JavaScript işlevi eklemek için, çağrıldığında, Age metin kutusunun değerini bir kalıcı ileti kutusunda görüntüler, Page_Load olay işleyicisine 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, Age TextBox 'ın ClientID özelliğinin değerini getElementByIdiçin JavaScript çağrısına çıkartır. Bu sayfayı bir tarayıcı aracılığıyla ziyaret ederseniz ve HTML kaynağını görüntülediğinizde, aşağıdaki JavaScript kodunu bulacaksınız:

<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>

ctl00_MainContent_Age``id özniteliği değerinin getElementByIdçağrısı içinde nasıl göründüğünü unutmayın. Bu değer çalışma zamanında hesaplandığı için, sayfa denetimi hiyerarşisinde daha sonraki değişikliklerden bağımsız olarak da kullanılır.

Note

Bu JavaScript örneği yalnızca bir sunucu denetimi tarafından işlenen HTML öğesine doğru şekilde başvuran 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 transpires olduğunda işlevi çağırmak için ek JavaScript yazmak gerekir. Bu ve ilgili konular hakkında daha fazla bilgi için, Istemci tarafı betiği Ile çalışmamakalesini okuyun.

Özet

Bazı ASP.NET Server denetimleri, kendi alt denetimlerinin işlenmiş id öznitelik değerlerini ve FindControl yöntemi tarafından canvassed 'ın kapsamını etkileyen adlandırma kapsayıcıları olarak davranır. Ana sayfaların yanı sıra, ana sayfanın kendisi ve ContentPlaceHolder denetimleri adlandırma kapsayıcılarıdır. Sonuç olarak, FindControlkullanarak içerik sayfası içindeki denetimlere programlı bir şekilde daha fazla iş yerleştirmemiz gerekir. Bu öğreticide, iki teknik inceliyoruz: ContentPlaceHolder denetimine detaya gitme ve FindControl metodunu çağırma. ve tüm adlandırma kapsayıcılarında yinelemeli olarak arama yapan FindControl kendi uygulamamızı yuvarlama.

Sunucu tarafı sorunları adlandırma kapsayıcılarının yanı sıra, Web denetimlerine başvurmayla ilgili olarak, istemci tarafı sorunları da vardır. Adlandırma kapsayıcıları yokluğunda, Web denetiminin ID Özellik değeri ve işlenmiş id öznitelik değeri aynı bir değerdir. Ancak, adlandırma kapsayıcısının eklenmesiyle, işlenen id özniteliği Web denetiminin hem ID değerlerini hem de denetim hiyerarşisinin aile içindeki adlandırma kapsayıcısını içerir. Bu adlandırma sorunları, Web denetiminin ClientID özelliğini kullandığınız ve istemci tarafı betikinizdeki işlenmiş id öznitelik değerini belirlemede olduğu sürece bir sorun değildir.

Programlamanın kutlu olsun!

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 Books ve 4GuysFromRolla.com 'in yazarı Scott Mitchell, 1998 sürümünden bu yana Microsoft Web teknolojileriyle birlikte çalışıyor. Scott bağımsız danışman, Trainer ve yazıcı olarak çalışıyor. En son kitabı, 24 saat içinde ASP.NET 3,5 kendi kendinize eğitimister. Scott 'a mitchell@4GuysFromRolla.com veya blogundan http://ScottOnWriting.NETüzerinden erişilebilir.

Özel olarak teşekkürler

Bu öğretici serisi birçok yararlı gözden geçirenler tarafından incelendi. Bu öğreticiye yönelik lider gözden geçirenler Zack Jones ve Suçi Barnerjee. Yaklaşan MSDN makalelerimi gözden geçiriyor musunuz? Öyleyse, beni mitchell@4GuysFromRolla.combir satır bırakın.