Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Scott Mitchell
Mengilustrasikan bagaimana kontrol ContentPlaceHolder berfungsi sebagai kontainer penamaan dan karenanya membuat bekerja secara terprogram dengan kontrol yang sulit (melalui FindControl). Lihat masalah dan solusinya. Juga membahas cara mengakses nilai ClientID yang dihasilkan secara terprogram.
Pengantar
Semua kontrol server ASP.NET mencakup ID
properti yang secara unik mengidentifikasi kontrol dan merupakan cara kontrol diakses secara terprogram di kelas code-behind. Demikian pula, elemen dalam dokumen HTML dapat menyertakan id
atribut yang secara unik mengidentifikasi elemen; nilai-nilai ini id
sering digunakan dalam skrip sisi klien untuk mereferensikan elemen HTML tertentu secara terprogram. Mengingat ini, Anda dapat berasumsi bahwa ketika kontrol server ASP.NET dirender ke dalam HTML, nilainya ID
digunakan sebagai id
nilai elemen HTML yang dirender. Ini belum tentu terjadi karena dalam keadaan tertentu kontrol tunggal dengan satu ID
nilai mungkin muncul beberapa kali dalam markup yang dirender. Pertimbangkan kontrol GridView yang menyertakan TemplateField dengan kontrol Label Web dengan ID
nilai ProductName. Ketika GridView terikat ke sumber datanya saat runtime, Label ini diulang sekali untuk setiap baris GridView. Setiap Label yang dirender membutuhkan nilai unik id
.
Untuk menangani skenario tersebut, ASP.NET memungkinkan kontrol tertentu ditandai sebagai kontainer penamaan. Kontainer penamaan berfungsi sebagai namespace baru ID
. Setiap kontrol server yang muncul dalam kontainer penamaan memiliki nilai yang dirender id
diawali dengan ID
kontrol kontainer penamaan. Misalnya, GridView
kelas dan GridViewRow
keduanya adalah penamaan kontainer. Akibatnya, kontrol Label yang ditentukan dalam GridView TemplateField dengan ID
ProductName diberi nilai yang dirender id
dari GridViewID_GridViewRowID_ProductName
. Karena GridViewRowID unik untuk setiap baris GridView, nilai yang dihasilkan id
bersifat unik.
Catatan
AntarmukaINamingContainer
digunakan untuk menunjukkan bahwa kontrol server ASP.NET tertentu harus berfungsi sebagai kontainer penamaan. Antarmuka INamingContainer
tidak mengeja metode apa pun yang harus diterapkan kontrol server; sebaliknya, antarmuka digunakan sebagai penanda. Dalam menghasilkan markup yang dirender, jika kontrol mengimplementasikan antarmuka ini, mesin ASP.NET secara otomatis mengawali nilainya ID
ke nilai atribut yang dirender id
keturunannya. Proses ini dibahas secara lebih rinci di Langkah 2.
Penamaan kontainer tidak hanya mengubah nilai atribut yang dirender id
, tetapi juga memengaruhi bagaimana kontrol dapat direferensikan secara terprogram dari kelas kode di belakang halaman ASP.NET. Metode FindControl("controlID")
ini umumnya digunakan untuk mereferensikan kontrol Web secara terprogram. Namun, FindControl
tidak menembus melalui penamaan kontainer. Akibatnya, Anda tidak dapat langsung menggunakan Page.FindControl
metode untuk mereferensikan kontrol dalam GridView atau kontainer penamaan lainnya.
Karena Anda mungkin telah menduga, halaman master dan ContentPlaceHolders keduanya diimplementasikan sebagai penamaan kontainer. Dalam tutorial ini kita memeriksa bagaimana halaman master memengaruhi nilai elemen id
HTML dan cara untuk mereferensikan kontrol Web secara terprogram dalam halaman konten menggunakan FindControl
.
Langkah 1: Menambahkan Halaman ASP.NET Baru
Untuk menunjukkan konsep yang dibahas dalam tutorial ini, mari kita tambahkan halaman ASP.NET baru ke situs web kami. Buat halaman konten baru bernama IDIssues.aspx
di folder akar, mengikatnya ke Site.master
halaman master.
Gambar 01: Tambahkan Halaman IDIssues.aspx
Konten ke Folder Akar
Visual Studio secara otomatis membuat kontrol Konten untuk setiap empat ContentPlaceHolder halaman master. Seperti yang disebutkan dalam tutorial Beberapa ContentPlaceHolders dan Konten Default , jika kontrol Konten tidak menyajikan konten ContentPlaceHolder default halaman master dipancarkan sebagai gantinya.
QuickLoginUI
Karena Dan LeftColumnContent
ContentPlaceHolders berisi markup default yang sesuai untuk halaman ini, lanjutkan dan hapus kontrol Konten terkait dari IDIssues.aspx
. Pada titik ini, markup deklaratif halaman konten akan terlihat seperti berikut ini:
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="IDIssues.aspx.cs" 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>
Dalam tutorial Menentukan Judul, Tag Meta, dan Header HTML Lainnya dalam tutorial Halaman Master , kami membuat kelas halaman dasar kustom (BasePage
) yang secara otomatis mengonfigurasi judul halaman jika tidak diatur secara eksplisit.
IDIssues.aspx
Agar halaman menggunakan fungsionalitas ini, kelas kode di belakang halaman harus berasal dari BasePage
kelas (bukan System.Web.UI.Page
). Ubah definisi kelas code-behind sehingga terlihat seperti berikut:
public partial class IDIssues : BasePage
{
}
Terakhir, perbarui Web.sitemap
file untuk menyertakan entri untuk pelajaran baru ini.
<siteMapNode>
Tambahkan elemen dan atur title
atribut dan url
ke "Masalah Penamaan ID Kontrol" dan ~/IDIssues.aspx
, masing-masing. Setelah membuat penambahan ini, markup file Anda Web.sitemap
akan terlihat mirip dengan yang berikut ini:
<?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>
Seperti yang diilustrasikan Gambar 2, entri peta situs baru di Web.sitemap
segera tercermin di bagian Pelajaran di kolom kiri.
Gambar 02: Bagian Pelajaran Sekarang Menyertakan Tautan ke "Masalah Penamaan ID Kontrol"
Langkah 2: Memeriksa Perubahan yang DirenderID
Untuk lebih memahami modifikasi yang dilakukan mesin ASP.NET ke nilai kontrol server yang dirender id
, mari kita tambahkan beberapa kontrol Web ke IDIssues.aspx
halaman lalu lihat markup yang dirender yang dikirim ke browser. Secara khusus, ketik teks "Harap masukkan usia Anda:" diikuti dengan kontrol Web TextBox. Lebih jauh ke bawah pada halaman menambahkan kontrol Web Tombol dan kontrol Web Label. Atur properti dan Columns
TextBox ID
ke Age
dan 3, masing-masing. Atur Properti dan ID
Tombol Text
ke "Kirim" dan SubmitButton
. Hapus properti Label Text
dan atur ID
ke Results
.
Pada titik ini markup deklaratif kontrol Konten Anda akan terlihat mirip dengan yang berikut ini:
<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>
Gambar 3 memperlihatkan halaman saat dilihat melalui desainer Visual Studio.
Gambar 03: Halaman Menyertakan Tiga Kontrol Web: Kotak Teks, Tombol, dan Label (Klik untuk melihat gambar ukuran penuh)
Kunjungi halaman melalui browser lalu lihat sumber HTML. Seperti yang ditunjukkan oleh markup di bawah ini, id
nilai elemen HTML untuk kontrol TextBox, Button, dan Label Web adalah kombinasi dari ID
nilai kontrol Web dan ID
nilai kontainer penamaan di halaman.
<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>
Seperti disebutkan sebelumnya dalam tutorial ini, halaman master dan ContentPlaceHolders berfungsi sebagai penamaan kontainer. Akibatnya, keduanya berkontribusi nilai yang dirender ID
dari kontrol berlapis mereka. Ambil atribut TextBox id
, misalnya: ctl00_MainContent_Age
. Ingat bahwa nilai kontrol ID
TextBox adalah Age
. Ini diawali dengan nilai kontrol ContentPlaceHolder-nya ID
, MainContent
. Selain itu, nilai ini diawali dengan nilai halaman ID
master, ctl00
. Efek bersih adalah nilai atribut yang id
terdiri dari ID
nilai halaman master, kontrol ContentPlaceHolder, dan TextBox itu sendiri.
Gambar 4 menggambarkan perilaku ini. Untuk menentukan yang dirender id
dari Age
TextBox, mulailah dengan ID
nilai kontrol TextBox, Age
. Selanjutnya, jalankan hierarki kontrol. Pada setiap kontainer penamaan (simpul tersebut dengan warna persik), awali saat ini yang dirender id
dengan kontainer id
penamaan .
Gambar 04: Atribut yang Dirender id
Didasarkan pada ID
Nilai Kontainer Penamaan
Catatan
Seperti yang kita bahas, ctl00
bagian dari atribut yang dirender id
merupakan ID
nilai halaman master, tetapi Anda mungkin bertanya-tanya bagaimana nilai ini ID
muncul. Kami tidak menentukannya di mana pun di halaman master atau konten kami. Sebagian besar kontrol server di halaman ASP.NET ditambahkan secara eksplisit melalui markup deklaratif halaman.
MainContent
Kontrol ContentPlaceHolder secara eksplisit ditentukan dalam markup Site.master
; Age
TextBox ditentukan IDIssues.aspx
markup. Kita dapat menentukan ID
nilai untuk jenis kontrol ini melalui jendela Properti atau dari sintaks deklaratif. Kontrol lain, seperti halaman master itu sendiri, tidak didefinisikan dalam markup deklaratif. Akibatnya, nilai-nilainya ID
harus dibuat secara otomatis untuk kita. Mesin ASP.NET menetapkan ID
nilai pada runtime untuk kontrol yang ID-nya belum diatur secara eksplisit. Ini menggunakan pola ctlXX
penamaan , di mana XX adalah nilai bilangan bulat yang meningkat secara berurutan.
Karena halaman master itu sendiri berfungsi sebagai kontainer penamaan, kontrol Web yang ditentukan di halaman master juga telah mengubah nilai atribut yang dirender id
. Misalnya, Label yang DisplayDate
kami tambahkan ke halaman master di tutorial Membuat Tata Letak Site-Wide dengan Halaman Master memiliki markup yang dirender berikut ini:
<span id="ctl00_DateDisplay">current date</span>
Perhatikan bahwa id
atribut menyertakan nilai halaman ID
master (ctl00
) dan ID
nilai kontrol Web Label (DateDisplay
).
Langkah 3: Mereferensikan Kontrol Web secara Terprogram melaluiFindControl
Setiap kontrol server ASP.NET menyertakan FindControl("controlID")
metode yang mencari turunan kontrol untuk kontrol bernama controlID. Jika kontrol seperti itu ditemukan, kontrol tersebut dikembalikan; jika tidak ada kontrol yang cocok yang ditemukan, FindControl
mengembalikan null
.
FindControl
berguna dalam skenario di mana Anda perlu mengakses kontrol tetapi Anda tidak memiliki referensi langsung ke dalamnya. Saat bekerja dengan kontrol Web data seperti GridView, misalnya, kontrol dalam bidang GridView ditentukan sekali dalam sintaks deklaratif, tetapi pada runtime instans kontrol dibuat untuk setiap baris GridView. Akibatnya, kontrol yang dihasilkan pada runtime ada, tetapi kami tidak memiliki referensi langsung yang tersedia dari kelas code-behind. Akibatnya, kita perlu menggunakan FindControl
untuk bekerja secara terprogram dengan kontrol tertentu dalam bidang GridView. (Untuk informasi selengkapnya tentang menggunakan FindControl
untuk mengakses kontrol dalam templat kontrol Web data, lihat Pemformatan Kustom Berdasarkan Data.) Skenario yang sama ini terjadi ketika secara dinamis menambahkan kontrol Web ke Formulir Web, topik yang dibahas dalam Membuat Antarmuka Pengguna Entri Data Dinamis.
Untuk mengilustrasikan menggunakan FindControl
metode untuk mencari kontrol dalam halaman konten, buat penanganan aktivitas untuk SubmitButton
Click
peristiwa. Di penanganan aktivitas, tambahkan kode berikut, yang secara terprogram mereferensikan Age
TextBox dan Results
Label menggunakan FindControl
metode lalu menampilkan pesan Results
berdasarkan input pengguna.
Catatan
Tentu saja, kita tidak perlu menggunakan FindControl
untuk mereferensikan kontrol Label dan TextBox untuk contoh ini. Kita dapat mereferensikannya langsung melalui nilai properti mereka ID
. Saya menggunakan FindControl
di sini untuk mengilustrasikan apa yang terjadi saat menggunakan FindControl
dari halaman konten.
protected void SubmitButton_Click(object sender, EventArgs e)
{
Label ResultsLabel = FindControl("Results") as Label;
TextBox AgeTextBox = Page.FindControl("Age") as TextBox;
ResultsLabel.Text = string.Format("You are {0} years old!", AgeTextBox.Text);
}
Sementara sintaks yang digunakan untuk memanggil FindControl
metode sedikit berbeda dalam dua baris SubmitButton_Click
pertama , mereka secara semantik setara. Ingat bahwa semua kontrol server ASP.NET menyertakan FindControl
metode . Ini termasuk Page
kelas , dari mana semua ASP.NET kelas di belakang kode harus berasal. Oleh karena itu, panggilan FindControl("controlID")
setara dengan memanggil Page.FindControl("controlID")
, dengan asumsi Anda belum mengambil alih FindControl
metode di kelas code-behind Anda atau di kelas dasar kustom.
Setelah memasukkan kode ini, kunjungi IDIssues.aspx
halaman melalui browser, masukkan usia Anda, dan klik tombol "Kirim". Setelah mengklik tombol "Kirim" a NullReferenceException
dinaikkan (lihat Gambar 5).
Gambar 05: A NullReferenceException
dinaikkan (Klik untuk melihat gambar ukuran penuh)
Jika Anda mengatur titik henti di SubmitButton_Click
penanganan aktivitas, Anda akan melihat bahwa kedua panggilan untuk FindControl
mengembalikan null
nilai.
NullReferenceException
dimunculkan ketika kita mencoba mengakses Age
properti TextBoxText
.
Masalahnya adalah hanya Control.FindControl
mencari keturunan Control yang berada dalam kontainer penamaan yang sama. Karena halaman master merupakan kontainer penamaan baru, panggilan untuk Page.FindControl("controlID")
tidak pernah meresap ke objek ctl00
halaman master . (Lihat kembali ke Gambar 4 untuk melihat hierarki kontrol, yang memperlihatkan Page
objek sebagai induk objek ctl00
halaman master .) Oleh karena itu, Label dan Age
Kotak Teks tidak ditemukan dan ResultsLabel
dan AgeTextBox
merupakan nilai yang ditetapkan dari null
.Results
Ada dua solusi untuk tantangan ini: kita dapat menelusuri paling detail, satu kontainer penamaan pada satu waktu, ke kontrol yang sesuai; atau kita dapat membuat metode kita sendiri FindControl
yang meresap ke kontainer penamaan. Mari kita periksa masing-masing opsi ini.
Menelusuri Kontainer Penamaan yang Sesuai
Untuk menggunakan FindControl
untuk mereferensikan Results
Label atau Age
Kotak Teks, kita perlu memanggil FindControl
dari kontrol leluhur dalam kontainer penamaan yang sama. Seperti yang ditunjukkan Gambar 4, MainContent
kontrol ContentPlaceHolder adalah satu-satunya Results
leluhur atau Age
yang berada dalam kontainer penamaan yang sama. Dengan kata lain, memanggil FindControl
metode dari MainContent
kontrol, seperti yang ditunjukkan pada cuplikan kode di bawah ini, mengembalikan referensi ke Results
kontrol atau Age
dengan benar.
Label ResultsLabel = MainContent.FindControl("Results") as Label;
TextBox AgeTextBox = MainContent.FindControl("Age") as TextBox;
Namun, kami tidak dapat bekerja dengan MainContent
ContentPlaceHolder dari kelas code-behind halaman konten kami menggunakan sintaks di atas karena ContentPlaceHolder ditentukan di halaman master. Sebaliknya, kita harus menggunakan FindControl
untuk mendapatkan referensi ke MainContent
. Ganti kode di penanganan SubmitButton_Click
aktivitas dengan modifikasi berikut:
protected void SubmitButton_Click(object sender, EventArgs e)
{
ContentPlaceHolder MainContent = FindControl("MainContent") as ContentPlaceHolder;
Label ResultsLabel = MainContent.FindControl("Results") as Label;
TextBox AgeTextBox = MainContent.FindControl("Age") as TextBox;
ResultsLabel.Text = string.Format("You are {0} years old!", AgeTextBox.Text);
}
Jika Anda mengunjungi halaman melalui browser, masukkan usia Anda, dan klik tombol "Kirim", NullReferenceException
akan dinaikkan. Jika Anda mengatur titik henti di SubmitButton_Click
penanganan aktivitas, Anda akan melihat bahwa pengecualian ini terjadi saat mencoba memanggil MainContent
metode objek FindControl
. Objek MainContent
ini karena null
FindControl
metode tidak dapat menemukan objek bernama "MainContent". Alasan yang mendasar sama dengan Results
kontrol Label dan Age
TextBox: FindControl
memulai pencariannya dari bagian atas hierarki kontrol dan tidak menembus kontainer penamaan, tetapi MainContent
ContentPlaceHolder berada dalam halaman master, yang merupakan kontainer penamaan.
Sebelum kita dapat menggunakan FindControl
untuk mendapatkan referensi ke MainContent
, pertama-tama kita memerlukan referensi ke kontrol halaman master. Setelah kita memiliki referensi ke halaman master, kita bisa mendapatkan referensi ke MainContent
ContentPlaceHolder melalui FindControl
dan, dari sana, referensi ke Results
Label dan Age
TextBox (lagi, melalui menggunakan FindControl
). Tapi bagaimana cara mendapatkan referensi ke halaman master? Dengan memeriksa id
atribut dalam markup yang dirender, terbukti bahwa nilai halaman ID
master adalah ctl00
. Oleh karena itu, kita dapat menggunakan Page.FindControl("ctl00")
untuk mendapatkan referensi ke halaman master, lalu menggunakan objek tersebut untuk mendapatkan referensi ke MainContent
, dan sebagainya. Cuplikan berikut mengilustrasikan logika ini:
// Get a reference to the master page
MasterPage ctl00 = FindControl("ctl00") as MasterPage;
// Get a reference to the ContentPlaceHolder
ContentPlaceHolder MainContent = ctl00.FindControl("MainContent") as ContentPlaceHolder;
// Reference the Label and TextBox controls
Label ResultsLabel = MainContent.FindControl("Results") as Label;
TextBox AgeTextBox = MainContent.FindControl("Age") as TextBox;
Meskipun kode ini pasti akan berfungsi, ia mengasumsikan bahwa halaman master yang dibuat secara otomatis ID
akan selalu ctl00
. Bukan ide yang baik untuk membuat asumsi tentang nilai yang dihasilkan secara otomatis.
Untungnya, referensi ke halaman master dapat diakses melalui Page
properti kelas Master
. Oleh karena itu, alih-alih harus menggunakan FindControl("ctl00")
untuk mendapatkan referensi halaman master untuk mengakses MainContent
ContentPlaceHolder, kita dapat menggunakan Page.Master.FindControl("MainContent")
. Perbarui penanganan SubmitButton_Click
aktivitas dengan kode berikut:
protected void SubmitButton_Click(object sender, EventArgs e)
{
ContentPlaceHolder MainContent = Page.Master.FindControl("MainContent") as ContentPlaceHolder;
Label ResultsLabel = MainContent.FindControl("Results") as Label;
TextBox AgeTextBox = MainContent.FindControl("Age") as TextBox;
ResultsLabel.Text = string.Format("You are {0} years old!", AgeTextBox.Text);
}
Kali ini, mengunjungi halaman melalui browser, memasukkan usia Anda, dan mengklik tombol "Kirim" menampilkan pesan di Results
Label, seperti yang diharapkan.
Gambar 06: Usia Pengguna Ditampilkan di Label (Klik untuk melihat gambar ukuran penuh)
Mencari Secara Rekursif Melalui Penamaan Kontainer
Alasan contoh kode sebelumnya mereferensikan MainContent
kontrol ContentPlaceHolder dari halaman master, lalu Results
kontrol Label dan Age
TextBox dari MainContent
, adalah karena Control.FindControl
metode hanya mencari dalam kontainer penamaan Control. Memiliki FindControl
tetap dalam kontainer penamaan masuk akal dalam sebagian besar skenario karena dua kontrol dalam dua kontainer penamaan yang berbeda mungkin memiliki nilai yang sama ID
. Pertimbangkan kasus GridView yang menentukan kontrol Web Label bernama ProductName
dalam salah satu TemplateFields-nya. Saat data terikat ke GridView saat runtime, ProductName
Label dibuat untuk setiap baris GridView. Jika FindControl
dicari melalui semua kontainer penamaan dan kami memanggil Page.FindControl("ProductName")
, instans Label apa yang harus FindControl
dikembalikan?
ProductName
Label di baris GridView pertama? Yang di baris terakhir?
Jadi memiliki Control.FindControl
pencarian hanya kontrol penamaan kontainer masuk akal dalam banyak kasus. Tetapi ada kasus lain, seperti yang menghadap kita, di mana kita memiliki yang unik ID
di semua kontainer penamaan dan ingin menghindari harus mereferensikan setiap kontainer penamaan dalam hierarki kontrol untuk mengakses kontrol. Memiliki FindControl
varian yang secara rekursif mencari semua kontainer penamaan juga masuk akal. Sayangnya, .NET Framework tidak menyertakan metode seperti itu.
Kabar baiknya adalah bahwa kita dapat membuat metode kita sendiri FindControl
yang secara rekursif mencari semua kontainer penamaan. Bahkan, menggunakan metode ekstensi kita dapat melakukan tack pada FindControlRecursive
metode ke Control
kelas untuk menyertai metode yang ada FindControl
.
Catatan
Metode ekstensi adalah fitur baru untuk C# 3.0 dan Visual Basic 9, yang merupakan bahasa yang dikirim dengan .NET Framework versi 3.5 dan Visual Studio 2008. Singkatnya, metode ekstensi memungkinkan pengembang membuat metode baru untuk jenis kelas yang ada melalui sintaks khusus. Untuk informasi selengkapnya tentang fitur bermanfaat ini, lihat artikel saya, Memperluas FungsiOnalitas Jenis Dasar dengan Metode Ekstensi.
Untuk membuat metode ekstensi, tambahkan file baru ke App_Code
folder bernama PageExtensionMethods.cs
. Tambahkan metode ekstensi bernama FindControlRecursive
yang mengambil sebagai input string
parameter bernama controlID
. Agar metode ekstensi berfungsi dengan baik, sangat penting bahwa kelas itu sendiri dan metode ekstensinya ditandai static
. Selain itu, semua metode ekstensi harus menerima sebagai parameter pertama mereka objek dari jenis yang diterapkan metode ekstensi, dan parameter input ini harus didahului dengan kata kunci this
.
Tambahkan kode berikut ke PageExtensionMethods.cs
file kelas untuk menentukan kelas ini dan FindControlRecursive
metode ekstensi:
using System;
using System.Web;
using System.Web.UI;
public static class PageExtensionMethods
{
public static Control FindControlRecursive(this Control ctrl, string controlID)
{
if (string.Compare(ctrl.ID, controlID, true) == 0)
{
// We found the control!
return ctrl;
}
else
{
// Recurse through ctrl's Controls collections
foreach (Control child in ctrl.Controls)
{
Control lookFor = FindControlRecursive(child, controlID);
if (lookFor != null)
return lookFor; // We found the control
}
// If we reach here, control was not found
return null;
}
}
}
Dengan kode ini di tempat, kembali ke IDIssues.aspx
kelas kode-di belakang halaman dan komentari panggilan metode saat ini FindControl
. Ganti dengan panggilan ke Page.FindControlRecursive("controlID")
. Yang rapi tentang metode ekstensi adalah metode tersebut muncul langsung dalam daftar drop-down IntelliSense. Seperti yang ditunjukkan Gambar 7, saat Anda mengetik Halaman lalu menekan periode, FindControlRecursive
metode disertakan dalam menu drop-down IntelliSense bersama dengan metode kelas lainnya Control
.
Gambar 07: Metode Ekstensi Disertakan dalam Drop-Downs IntelliSense (Klik untuk melihat gambar ukuran penuh)
Masukkan kode berikut ke SubmitButton_Click
dalam penanganan aktivitas lalu uji dengan mengunjungi halaman, memasukkan usia Anda, dan mengklik tombol "Kirim". Seperti yang ditunjukkan kembali pada Gambar 6, output yang dihasilkan akan menjadi pesan, "Anda berusia tahun!"
protected void SubmitButton_Click(object sender, EventArgs e)
{
Label ResultsLabel = Page.FindControlRecursive("Results") as Label;
TextBox AgeTextBox = Page.FindControlRecursive("Age") as TextBox;
ResultsLabel.Text = string.Format("You are {0} years old!", AgeTextBox.Text);
}
Catatan
Karena metode ekstensi baru untuk C# 3.0 dan Visual Basic 9, jika Anda menggunakan Visual Studio 2005, Anda tidak dapat menggunakan metode ekstensi. Sebagai gantinya FindControlRecursive
, Anda harus menerapkan metode di kelas pembantu.
Rick Strahl memiliki contoh seperti itu dalam posting blognya, ASP.NET Maser Pages dan FindControl
.
Langkah 4: Menggunakan Nilai Atribut yang Benarid
di Skrip Client-Side
Seperti yang disebutkan dalam pengenalan tutorial ini, atribut yang dirender kontrol Web sering digunakan dalam skrip sisi klien untuk mereferensikan id
elemen HTML tertentu secara terprogram. Misalnya, JavaScript berikut mereferensikan elemen HTML dengannya id
lalu menampilkan nilainya dalam kotak pesan modal:
var elem = document.getElementById("Age");
if (elem != null)
alert("You entered " + elem.value + " into the Age text box.");
Ingat bahwa di halaman ASP.NET yang tidak menyertakan kontainer penamaan, atribut elemen id
HTML yang dirender identik dengan nilai properti kontrol ID
Web. Karena itu, menggoda untuk hard code dalam id
nilai atribut ke dalam kode JavaScript. Artinya, jika Anda tahu ingin mengakses Age
kontrol Web TextBox melalui skrip sisi klien, lakukan melalui panggilan ke document.getElementById("Age")
.
Masalah dengan pendekatan ini adalah bahwa saat menggunakan halaman master (atau kontrol kontainer penamaan lainnya), HTML id
yang dirender tidak identik dengan properti kontrol ID
Web. Kenaikan pertama Anda mungkin adalah mengunjungi halaman melalui browser dan melihat sumber untuk menentukan atribut aktual id
. Setelah mengetahui nilai yang dirender id
, Anda dapat menempelkannya ke panggilan untuk getElementById
mengakses elemen HTML yang perlu Anda kerjakan melalui skrip sisi klien. Pendekatan ini kurang ideal karena perubahan tertentu pada hierarki kontrol halaman atau perubahan pada ID
properti kontrol penamaan akan mengubah atribut yang dihasilkan id
, sehingga melanggar kode JavaScript Anda.
Kabar baiknya adalah bahwa id
nilai atribut yang dirender dapat diakses dalam kode sisi server melalui properti kontrol ClientID
Web. Anda harus menggunakan properti ini untuk menentukan nilai atribut yang id
digunakan dalam skrip sisi klien. Misalnya, untuk menambahkan fungsi JavaScript ke halaman yang, saat dipanggil, menampilkan nilai Age
Kotak Teks dalam kotak pesan modal, tambahkan kode berikut ke Page_Load
penanganan aktivitas:
ClientScript.RegisterClientScriptBlock(this.GetType(), "ShowAgeTextBoxScript",
string.Format(@"function ShowAge()
{{
var elem = document.getElementById('{0}');
if (elem != null)
alert('You entered ' + elem.value + ' into the Age text box.');
}}", AgeTextBox.ClientID), true);
Kode di atas menyuntikkan nilai Age
properti ClientID TextBox ke dalam panggilan JavaScript ke getElementById
. Jika Anda mengunjungi halaman ini melalui browser dan melihat sumber HTML, Anda akan menemukan kode JavaScript berikut:
<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>
Perhatikan bagaimana nilai atribut yang benar id
, ctl00_MainContent_Age
, muncul dalam panggilan ke getElementById
. Karena nilai ini dihitung saat runtime, nilai ini berfungsi terlepas dari perubahan selanjutnya pada hierarki kontrol halaman.
Catatan
Contoh JavaScript ini hanya menunjukkan cara menambahkan fungsi JavaScript yang mereferensikan elemen HTML dengan benar yang dirender oleh kontrol server. Untuk menggunakan fungsi ini, Anda perlu menulis JavaScript tambahan untuk memanggil fungsi saat dokumen dimuat atau ketika beberapa tindakan pengguna tertentu bertranspitasi. Untuk informasi selengkapnya tentang topik ini dan topik terkait, baca Bekerja dengan Skrip Client-Side.
Ringkasan
Kontrol server ASP.NET tertentu bertindak sebagai penamaan kontainer, yang memengaruhi nilai atribut yang dirender id
dari kontrol keturunannya serta cakupan kontrol yang dikanvas oleh FindControl
metode . Sehubungan dengan halaman master, halaman master itu sendiri dan kontrol ContentPlaceHolder-nya adalah penamaan kontainer. Akibatnya, kita perlu meluangkan sedikit lebih banyak pekerjaan untuk mereferensikan kontrol secara terprogram dalam halaman konten menggunakan FindControl
. Dalam tutorial ini kami memeriksa dua teknik: menelusuri kontrol ContentPlaceHolder dan memanggil metodenya FindControl
; dan menggulirkan implementasi kami sendiri FindControl
yang secara rekursif mencari melalui semua kontainer penamaan.
Selain masalah sisi server penamaan kontainer yang diperkenalkan sehubungan dengan mereferensikan kontrol Web, ada juga masalah sisi klien. Dengan tidak adanya penamaan kontainer, nilai properti kontrol ID
Web dan nilai atribut yang dirender id
adalah satu dalam hal yang sama. Tetapi dengan penamaan kontainer, atribut yang dirender id
mencakup ID
nilai kontrol Web dan kontainer penamaan dalam hierarki kontrolnya. Masalah penamaan ini adalah non-masalah selama Anda menggunakan properti kontrol ClientID
Web untuk menentukan nilai atribut yang dirender id
dalam skrip sisi klien Anda.
Selamat Pemrograman!
Bacaan lebih lanjut
Untuk informasi selengkapnya tentang topik yang dibahas dalam tutorial ini, lihat sumber daya berikut:
-
ASP.NET Halaman Master dan
FindControl
- Membuat Antarmuka Pengguna Entri Data Dinamis
- Cara: Referensi ASP.NET Konten Halaman Master
- Halaman Mater: Tips, Trik, dan Perangkap
- Bekerja dengan Skrip Client-Side
Tentang Penulis
Scott Mitchell, penulis beberapa buku ASP/ASP.NET dan pendiri 4GuysFromRolla.com, telah bekerja dengan teknologi Microsoft Web sejak 1998. Scott bekerja sebagai konsultan independen, pelatih, dan penulis. Buku terbarunya adalah Sams Teach Yourself ASP.NET 3.5 dalam 24 Jam. Scott dapat dijangkau di mitchell@4GuysFromRolla.com atau melalui blognya di http://ScottOnWriting.NET.
Terima Kasih Khusus Kepada
Seri tutorial ini ditinjau oleh banyak peninjau yang membantu. Peninjau utama untuk tutorial ini adalah Zack Jones dan Suchi Barnerjee. Tertarik untuk meninjau artikel MSDN saya yang akan datang? Jika demikian, jatuhkan saya baris di mitchell@4GuysFromRolla.com.