İçerik Sayfalarında Denetim Kimliği Adlandırma (VB)
tarafından Scott Mitchell
ContentPlaceHolder denetimlerinin bir adlandırma kapsayıcısı olarak nasıl görev yapacağı 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 bakın. 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 denetimin arka kod arkası sınıfında program aracılığıyla erişilme yöntemidir. Benzer şekilde, bir HTML belgesindeki öğeler öğeyi benzersiz olarak tanımlayan bir id
öznitelik içerebilir; bu id
değerler genellikle belirli bir HTML öğesine program aracılığıyla başvurmak için istemci tarafı betiğinde kullanılır. Bunu göz önünde bulundurarak, bir ASP.NET sunucu denetimi HTML olarak 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ünebileceğinden, bu durum mutlaka böyle değildir. değeriyle ProductName
Label Web denetimine sahip templateField içeren bir ID
GridView denetimini göz önünde bulundurun. GridView çalışma zamanında veri kaynağına bağlı olduğunda, 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 denetimlerinin işlenen id
değerlerine adlandırma kapsayıcısı denetiminin ID
ön ekini ekler. Örneğin, GridView
ve GridViewRow
sınıflarının her ikisi de adlandırma kapsayıcılarıdır. Sonuç olarak, ile ID
ProductName
GridView TemplateField içinde tanımlanan etiket denetimine GridViewID_GridViewRowID_ProductName
iş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ı değerini alt öğelerine ait işlenen id
öznitelik değerlerine otomatik olarak öneklerID
. 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 denetime ASP.NET sayfasının arka kod arkası sınıfından 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, bir GridView veya başka bir adlandırma kapsayıcısı Page.FindControl
içindeki denetimlere başvurmak için yöntemini doğrudan kullanamazsınız.
Sizin de izlenmiş olabileceğiniz gibi, ana sayfalar ve ContentPlaceHolders adlandırma kapsayıcıları olarak uygulanır. Bu öğreticide, ana sayfaların HTML öğesi id
değerlerini nasıl etkilediğini ve kullanarak FindControl
içerik sayfasındaki Web denetimlerine program aracılığıyla başvurma 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
ve ana sayfaya Site.master
bağlayan yeni bir içerik sayfası oluşturun.
Ş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şaretleme içerdiğinden, devam edin ve ilgili İçerik denetimlerini uygulamasından IDIssues.aspx
kaldı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 Sayfada Başlık, Meta Etiketler ve Diğer HTML Üst Bilgilerini Belirtme öğreticisinde, açıkça ayarlanmazsa 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.aspx
olarak ayarlayın. Bu ekleme tamamlandıktan 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.
Şekil 02: Dersler Bölümü Artık "Denetim Kimliği Adlandırma Sorunları" bağlantısını içerir
2. Adım: İşlenenID
Değ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üğme Text
ID
ve özelliklerini "Gönder" ve SubmitButton
olarak ayarlayın. Label Text
özelliğini temizleyin ve olarak ayarlayın ID
Results
.
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 tasarımcısı aracılığıyla görüntülendiğinde sayfa gösterilir.
Ş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 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 ID
değerleri, Web denetimlerinin değerlerinin ve ID
sayfadaki adlandırma kapsayıcılarının değerlerinin bir bileş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 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 Age
hatırlayın. Bu, ContentPlaceHolder denetiminin ID
değeriyle MainContent
önek olarak eklenir. Ayrıca, bu değer ana sayfanın ID
değeri ctl00
olan ön ekini alır. Net etkisi, ana sayfanın değerlerinden, ContentPlaceHolder denetiminden 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 Age
değeriyle ID
başlayın. Ardından, denetim hiyerarşisinde 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 ön ekini koyun id
.
Şekil 04: İşlenen id
Öznitelikler Adlandırma Kapsayıcılarının Değerlerini Temel Alır ID
Not
Daha önce de belirttiğimiz 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 geldiğini merak ediyor olabilirsiniz. Ana sayfamızın veya içerik sayfamızın herhangi bir yerinde 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, işaretlemesinde Site.master
açı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
. XX'in sıralı olarak artan bir tamsayı değeri olduğu adlandırma desenini ctlXX
kullanır.
Ana sayfanın kendisi bir adlandırma kapsayıcısı görevi görmesi nedeniyle, ana sayfada tanımlanan Web denetimleri de işlenmiş öznitelik değerlerini değiştirmektedir id
. Örneğin, DisplayDate
Ana Sayfalarla Site-Wide Düzeni 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 denetime doğrudan başvuruya sahip olmadığınız 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ındaki 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 SubmitButton
bir olay işleyicisi oluşturun. Olay işleyicisine, yöntemini kullanarak FindControl
TextBox ve Label'a program aracılığıyla başvuran Age
ve Results
ardından kullanıcının girişlerine göre içinde Results
bir ileti görüntüleyen aşağıdaki kodu ekleyin.
Not
Elbette, bu örnek için 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
ne 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_Click
biraz 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ını içerir Page
. Bu nedenle, FindControl("controlID")
arka 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ı 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).
Ş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ü Nothing
görürsünüz. NullReferenceException
, TextBox'ın Text
özelliğine erişmeyi denediğimizde Age
oluşturulur.
Sorun, Control.FindControl
yalnızca Aynı adlandırma kapsayıcısında bulunan Control'ün alt öğelerini aramadır. Ana sayfa yeni bir adlandırma kapsayıcısı oluşturduğundan, ana sayfa nesnesine ctl00
hiçbir zaman geçirilmeme Page.FindControl("controlID")
çağrısı yapılır. (Nesneyi ana sayfa ctl00
nesnesinin ü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 Nothing
atanır.
Bu sınamanın iki geçici çözümü vardır: uygun denetime tek seferde bir adlandırma kapsayıcısı olmak üzere detaya gidebiliriz; veya adlandırma kapsayıcılarına nüfuz eden 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ısı 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 başvuru almak için kullanmamız FindControl
gerekir MainContent
. 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 bir kesme noktası ayarlarsanız, nesnenin SubmitButton_Click
FindControl
yöntemini çağırmaya çalışırken bu özel durumun gerçekleştiğini 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 aracılığıyla (yine kullanarakFindControl
) bir başvuru alacağız. Ama ana sayfaya nasıl başvuru alacağız? İşlenen işaretlemedeki öznitelikleri inceleyerek id
ana sayfanın ID
değerinin olduğu ctl00
açıktır. Bu nedenle, ana sayfaya başvuru almak için kullanabilir Page.FindControl("ctl00")
, ardından bu nesneyi kullanarak öğesine başvuru MainContent
alabilir ve bu şekilde devam edebiliriz. 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ı ctl00
varsayar. Otomatik 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 sayfanın başvurularını almak için kullanmak FindControl("ctl00")
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ığınızda, ileti etikette Results
beklendiği gibi görüntülenir.
Şekil 06: Etikette Kullanıcının Yaşı 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
Label ve Age
TextBox denetimlerinin MainContent
nedeni, yöntemin Control.FindControl
yalnızca Control'ün adlandırma kapsayıcısında aramasıdır. İki FindControl
farklı adlandırma kapsayıcısında bulunan 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ğlı olduğunda, 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 yalnızca Control'ün adlandırma kapsayıcısında arama yapmak Control.FindControl
çoğu durumda mantıklıdır. Ancak, tüm adlandırma kapsayıcılarında benzersiz ID
bir öğeye sahip olduğumuz ve bir denetime erişmek için denetim hiyerarşisindeki her adlandırma kapsayıcısına titizlikle başvurmak zorunda kalmamak istediğimiz, bize bakan durum gibi başka durumlar da vardır. Tüm adlandırma kapsayıcılarında özyinelemeli olarak 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 bağlanabiliriz.
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'a yeni eklenen 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öntemleri ile Temel Tür İşlevselliğini Genişletme makaleme bakın.
Uzantı yöntemini oluşturmak için adlı PageExtensionMethods.vb
klasöre App_Code
yeni bir dosya ekleyin. adlı bir parametre girişi olarak alan adlı FindControlRecursive
controlID
bir String
uzantı yöntemi ekleyin. 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 ilk parametre olarak uzantı yönteminin uygulandığı türde bir nesneyi 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 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, bunların doğrudan IntelliSense açılan listelerinde görünmesidir. Şekil 7'de gösterildiği gibi, yazıp Page
nokta tuşuna FindControlRecursive
bastığınızda, yöntem diğer Control
sınıf yöntemleriyle birlikte IntelliSense açılan menüsüne eklenir.
Şekil 07: Uzantı Yöntemleri IntelliSense Drop-Downs 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 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 çıkış "Yaşınız bu!" iletisidir.
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' ın blog gönderisinde Maser Pages ve FindControl
ASP.NET böyle bir örneği vardır.
4. Adım: Client-Side 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 tarafından id
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 uygulamak 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ıyla document.getElementById("Age")
yapın.
Bu yaklaşımdaki sorun, ana sayfaları (veya diğer adlandırma kapsayıcı 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 çağrısına getElementById
yapıştırabilirsiniz. Sayfanın denetim hiyerarşisinde yapılan belirli değişiklikler veya adlandırma denetimlerinin özelliklerinde yapılan 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 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_Age
içinde nasıl göründüğüne getElementById
dikkat 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ışı bırakıldığında işlevi çağırmak için ek JavaScript yazmanız gerekir. Bu ve ilgili konular hakkında daha fazla bilgi için bkz. Client-Side Betiği ile çalışma.
Özet
Bazı ASP.NET sunucu denetimleri, alt denetimlerinin işlenen öznitelik değerlerini ve yöntemi tarafından FindControl
tuvallenen id
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 FindControl
iç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.
Kapsayıcıları adlandırmanın Web denetimlerine başvurmayla ilgili olarak ortaya koyan sunucu tarafı sorunlarına ek olarak, istemci tarafı sorunları da vardır. Kapsayıcıları adlandırma 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 birlikte, işlenen id
öznitelik hem Web denetiminin değerlerini hem de ID
denetim hiyerarşisinin atalarındaki adlandırma kapsayıcılarını içerir. İstemci tarafı betiğinizde işlenen id
öznitelik değerini belirlemek için Web denetiminin ClientID
özelliğini kullandığınız sürece bu adlandırma endişeleri sorun oluşturmaz.
Mutlu Programlama!
Daha Fazla Bilgi
Bu öğreticide ele alınan konular hakkında daha fazla bilgi için aşağıdaki kaynaklara bakın:
- Ana Sayfaları ASP.NET ve
FindControl
- Dinamik Veri Girişi Kullanıcı Arabirimleri Oluşturma
- Nasıl yapılır: Ana Sayfa İçeriği ASP.NET Başvuru
- Mater Sayfaları: İpuçları, Püf Noktaları ve Tuzaklar
- Client-Side Betiği ile Çalışma
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ışmaktadı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 bir satır mitchell@4GuysFromRolla.combırakın.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin