Bagikan melalui


Menyisipkan Rekaman Baru dari Footer GridView (C#)

oleh Scott Mitchell

Unduh PDF

Meskipun kontrol GridView tidak menyediakan dukungan bawaan untuk menyisipkan rekaman data baru, tutorial ini menunjukkan cara menambah GridView untuk menyertakan antarmuka penyisipan.

Pendahuluan

Seperti yang dibahas dalam tutorial Gambaran Umum Menyisipkan, Memperbarui, dan Menghapus Data , kontrol Web GridView, DetailsView, dan FormView masing-masing menyertakan kemampuan modifikasi data bawaan. Ketika digunakan dengan kontrol sumber data deklaratif, ketiga kontrol Web ini dapat dengan cepat dan mudah dikonfigurasi untuk memodifikasi data - dan dalam skenario tanpa perlu menulis satu baris kode. Sayangnya, hanya kontrol DetailsView dan FormView yang menyediakan kemampuan penyisipan, pengeditan, dan penghapusan bawaan. GridView hanya menawarkan dukungan pengeditan dan penghapusan. Namun, dengan sedikit kerja keras, kita dapat mengembangkan GridView untuk menyertakan antarmuka penyisipan.

Dalam menambahkan kemampuan penyisipan ke GridView, kami bertanggung jawab untuk memutuskan bagaimana rekaman baru akan ditambahkan, membuat antarmuka penyisipan, dan menulis kode untuk menyisipkan rekaman baru. Dalam tutorial ini kita akan melihat menambahkan antarmuka penyisipan ke baris footer GridView (lihat Gambar 1). Sel footer untuk setiap kolom menyertakan elemen antarmuka pengguna pengumpulan data yang sesuai (TextBox untuk nama produk, DropDownList untuk pemasok, dan sebagainya). Kita juga memerlukan kolom untuk tombol Tambahkan yang, ketika diklik, akan mengakibatkan postback dan menyisipkan rekaman baru ke dalam tabel Products menggunakan nilai yang disediakan di baris footer.

Baris Footer Menyediakan Antarmuka untuk Menambahkan Produk Baru

Gambar 1: Baris Footer Menyediakan Antarmuka untuk Menambahkan Produk Baru (Klik untuk melihat gambar ukuran penuh)

Langkah 1: Menampilkan Informasi Produk di GridView

Sebelum kita merisaukan pembuatan antarmuka penyisipan di footer GridView, mari kita fokus terlebih dahulu pada menambah GridView pada halaman yang mencantumkan produk dari database. Mulailah dengan membuka halaman InsertThroughFooter.aspx di folder EnhancedGridView dan seret sebuah GridView dari Toolbox ke Designer, lalu atur properti GridView tersebut ke IDProducts. Selanjutnya, gunakan tag pintar GridView untuk mengikatnya ke ObjectDataSource baru bernama ProductsDataSource.

Membuat ObjectDataSource Baru bernama ProductsDataSource

Gambar 2: Buat ObjectDataSource Baru Bernama ProductsDataSource (Klik untuk melihat gambar ukuran penuh)

Konfigurasikan ObjectDataSource untuk menggunakan metode ProductsBLL dari kelas GetProducts() untuk mengambil informasi produk. Untuk tutorial ini, mari kita fokus secara ketat pada penambahan kemampuan penyisipan dan tidak khawatir tentang pengeditan dan penghapusan. Oleh karena itu, pastikan bahwa daftar drop-down di tab INSERT diatur ke AddProduct() dan daftar drop-down di tab PERBARUI dan HAPUS diatur ke (Tidak Ada) .

Memetakan Metode AddProduct ke Metode Insert() ObjectDataSource

Gambar 3: Petakan AddProduct Metode ke Metode ObjectDataSource s Insert() (Klik untuk melihat gambar ukuran penuh)

Atur UPDATE dan DELETE Daftar Tab Drop-Down ke Tidak ada

Gambar 4: Atur Tab UPDATE dan DELETE pada Daftar Drop-Down ke (Tidak Ada) (Klik untuk melihat gambar ukuran penuh)

Setelah menyelesaikan wizard Konfigurasi Sumber Data ObjectDataSource, Visual Studio akan secara otomatis menambahkan bidang ke GridView untuk setiap bidang data terkait. Untuk saat ini, biarkan semua bidang yang ditambahkan oleh Visual Studio. Nanti dalam tutorial ini kita akan kembali dan menghapus beberapa bidang yang nilainya tidak perlu ditentukan saat menambahkan rekaman baru.

Karena ada hampir 80 produk dalam database, pengguna harus menggulir ke bawah ke bagian bawah halaman web untuk menambahkan rekaman baru. Oleh karena itu, mari aktifkan pengaturan halaman agar antarmuka penyisipan lebih jelas dan mudah diakses. Untuk mengaktifkan paging, cukup centang kotak Centang Aktifkan Paging dari tag pintar GridView.

Pada titik ini, markup deklaratif GridView dan ObjectDataSource akan terlihat mirip dengan yang berikut ini:

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    AllowPaging="True" EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID" 
            InsertVisible="False" ReadOnly="True" 
            SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="ProductName" 
            SortExpression="ProductName" />
        <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" 
            SortExpression="SupplierID" />
        <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" 
            SortExpression="CategoryID" />
        <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" 
            SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" 
            SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" 
            SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" 
            SortExpression="UnitsOnOrder" />
        <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" 
            SortExpression="ReorderLevel" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" 
            SortExpression="Discontinued" />
        <asp:BoundField DataField="CategoryName" HeaderText="CategoryName" 
            ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="SupplierName" 
            ReadOnly="True" SortExpression="SupplierName" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}" 
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <InsertParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
        <asp:Parameter Name="categoryID" Type="Int32" />
        <asp:Parameter Name="quantityPerUnit" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="unitsInStock" Type="Int16" />
        <asp:Parameter Name="unitsOnOrder" Type="Int16" />
        <asp:Parameter Name="reorderLevel" Type="Int16" />
        <asp:Parameter Name="discontinued" Type="Boolean" />
    </InsertParameters>
</asp:ObjectDataSource>

Semua Bidang Data Produk Ditampilkan di Paged GridView

Gambar 5: Semua Bidang Data Produk Ditampilkan dalam Tampilan Kisi Halaman (Klik untuk melihat gambar ukuran penuh)

Bersama dengan header dan baris datanya, GridView menyertakan baris footer. Baris header dan footer ditampilkan tergantung pada nilai dari properti ShowHeader dan ShowFooter GridView. Untuk menampilkan baris footer, cukup atur properti ke ShowFootertrue. Seperti yang diilustrasikan pada Gambar 6, mengatur properti ShowFooter ke true menambahkan baris footer ke kisi.

Untuk Menampilkan Baris Footer, Atur ShowFooter ke True

Gambar 6: Untuk Menampilkan Baris Footer, Atur ShowFooter ke True (Klik untuk melihat gambar ukuran penuh)

Perhatikan bahwa baris footer memiliki warna latar belakang merah tua. Hal ini disebabkan oleh Tema DataWebControls yang kami buat dan terapkan ke semua halaman kembali dalam tutorial Menampilkan Data Dengan ObjectDataSource . Secara khusus, GridView.skin file mengonfigurasi FooterStyle properti agar menggunakan FooterStyle CSS kelas. Kelas FooterStyle didefinisikan dalam Styles.css sesuai berikut:

.FooterStyle
{
    background-color: #a33;
    color: White;
    text-align: right;
}

Nota

Kami telah menjelajahi menggunakan baris footer GridView di tutorial sebelumnya. Jika diperlukan, rujuk kembali ke tutorial Menampilkan Informasi Ringkasan dalam Footer GridView untuk penyegaran.

Setelah mengatur ShowFooter properti ke true, luangkan waktu sejenak untuk melihat output di browser. Saat ini baris footer tidak berisi teks atau kontrol Web apa pun. Di Langkah 3 kita akan memodifikasi footer untuk setiap bidang GridView sehingga mencakup antarmuka penyisipan yang sesuai.

Baris Footer Kosong Ditampilkan di Atas Kontrol Navigasi Halaman

Gambar 7: Baris Footer Kosong Ditampilkan di Atas Kontrol Antarmuka Navigasi (Klik untuk melihat gambar ukuran penuh)

Kembali ke tutorial Menggunakan TemplateFields di GridView Control , kami melihat cara mengkustomisasi tampilan kolom GridView tertentu dengan sangat baik menggunakan TemplateFields (dibandingkan dengan BoundFields atau CheckBoxFields); dalam Menyesuaikan Antarmuka Modifikasi Data yang kami lihat menggunakan TemplateFields untuk menyesuaikan antarmuka pengeditan di GridView. Ingat bahwa TemplateField terdiri dari sejumlah templat yang menentukan campuran markup, kontrol Web, dan sintaks pengikatan data yang digunakan untuk jenis baris tertentu. ItemTemplate, misalnya, menentukan templat yang digunakan untuk baris baca-saja, sementara EditItemTemplate menentukan templat untuk baris yang dapat diedit.

Bersama dengan ItemTemplate dan EditItemTemplate, TemplateField juga menyertakan FooterTemplate yang menentukan konten untuk baris footer. Oleh karena itu, kita dapat menambahkan kontrol Web yang diperlukan untuk antarmuka penambahan setiap bidang ke dalam FooterTemplate. Untuk memulai, konversikan semua bidang di GridView ke TemplateFields. Ini dapat dilakukan dengan mengklik tautan Edit Kolom di tag pintar GridView, memilih setiap bidang di sudut kiri bawah, dan mengklik tautan Konversi bidang ini menjadi TemplateField.

Mengonversi Setiap Bidang Menjadi Bidang Templat

Gambar 8: Mengonversi Setiap Bidang Menjadi Bidang Templat

Mengklik Ubah bidang ini menjadi TemplateField akan mengubah jenis bidang saat ini menjadi TemplateField yang setara. Misalnya, setiap BoundField digantikan oleh TemplateField dengan ItemTemplate yang berisi Label yang menampilkan bidang data terkait dan EditItemTemplate yang menampilkan bidang data di Kotak Teks. ProductName BoundField telah dikonversi menjadi markup TemplateField berikut:

<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
    <EditItemTemplate>
        <asp:TextBox ID="TextBox1" runat="server" 
            Text='<%# Bind("ProductName") %>'></asp:TextBox>
    </EditItemTemplate>
    <ItemTemplate>
        <asp:Label ID="Label2" runat="server" 
            Text='<%# Bind("ProductName") %>'></asp:Label>
    </ItemTemplate>
</asp:TemplateField>

Demikian juga, Discontinued CheckBoxField telah dikonversi menjadi TemplateField di mana ItemTemplate dan EditItemTemplate mengandung kontrol Web CheckBox (dengan CheckBox pada ItemTemplate dinonaktifkan). BoundField hanya-baca ProductID telah dikonversi menjadi TemplateField dengan kontrol Label di ItemTemplate dan EditItemTemplate. Singkatnya, mengonversi bidang GridView yang ada menjadi TemplateField adalah cara cepat dan mudah untuk beralih ke TemplateField yang lebih dapat disesuaikan tanpa kehilangan salah satu fungsionalitas bidang yang ada.

GridView yang digunakan tidak mendukung pengeditan, silakan hapus EditItemTemplate dari setiap TemplateField, menyisakan hanya ItemTemplate. Setelah melakukan ini, markup deklaratif GridView Anda akan terlihat seperti berikut ini:

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    AllowPaging="True" EnableViewState="False" ShowFooter="True">
    <Columns>
        <asp:TemplateField HeaderText="ProductID" InsertVisible="False" 
            SortExpression="ProductID">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" 
                    Text='<%# Bind("ProductID") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" 
                    Text='<%# Bind("ProductName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="SupplierID" SortExpression="SupplierID">
            <ItemTemplate>
                <asp:Label ID="Label3" runat="server" 
                    Text='<%# Bind("SupplierID") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="CategoryID" SortExpression="CategoryID">
            <ItemTemplate>
                <asp:Label ID="Label4" runat="server" 
                    Text='<%# Bind("CategoryID") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="QuantityPerUnit" 
            SortExpression="QuantityPerUnit">
            <ItemTemplate>
                <asp:Label ID="Label5" runat="server" 
                    Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="UnitPrice" SortExpression="UnitPrice">
            <ItemTemplate>
                <asp:Label ID="Label6" runat="server" 
                    Text='<%# Bind("UnitPrice") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="UnitsInStock" 
            SortExpression="UnitsInStock">
            <ItemTemplate>
                <asp:Label ID="Label7" runat="server" 
                    Text='<%# Bind("UnitsInStock") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="UnitsOnOrder" 
            SortExpression="UnitsOnOrder">
            <ItemTemplate>
                <asp:Label ID="Label8" runat="server" 
                    Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="ReorderLevel" 
            SortExpression="ReorderLevel">
            <ItemTemplate>
                <asp:Label ID="Label9" runat="server" 
                    Text='<%# Bind("ReorderLevel") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Discontinued" 
            SortExpression="Discontinued">
            <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server" 
                    Checked='<%# Bind("Discontinued") %>' Enabled="false" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="CategoryName" 
            SortExpression="CategoryName">
            <ItemTemplate>
                <asp:Label ID="Label10" runat="server" 
                    Text='<%# Bind("CategoryName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="SupplierName" 
            SortExpression="SupplierName">
            <ItemTemplate>
                <asp:Label ID="Label11" runat="server" 
                    Text='<%# Bind("SupplierName") %>'></asp:Label>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Sekarang setelah setiap bidang GridView telah dikonversi menjadi TemplateField, kita dapat memasukkan antarmuka penyisipan yang sesuai ke setiap bidang .FooterTemplate Beberapa bidang tidak akan memiliki antarmuka penyisipan (ProductID, misalnya); yang lain akan bervariasi dalam kontrol Web yang digunakan untuk mengumpulkan informasi produk baru.

Untuk membuat antarmuka pengeditan, pilih tautan Edit Templat dari tag pintar GridView. Kemudian, dari daftar drop-down, pilih bidang yang FooterTemplate sesuai dan seret kontrol yang sesuai dari Kotak Alat ke Perancang.

Tambahkan Antarmuka Pemasukan yang Tepat ke Template Footer di Setiap Bidang

Gambar 9: Tambahkan Antarmuka Penyisipan yang Sesuai ke Setiap Bidang (FooterTemplateKlik untuk melihat gambar ukuran penuh)

Daftar berpoin berikut menghitung bidang GridView, menentukan antarmuka penyisipan yang akan ditambahkan:

  • ProductID tidak.
  • ProductName tambahkan TextBox dan atur ID ke NewProductName. Tambahkan kontrol RequiredFieldValidator juga untuk memastikan bahwa pengguna memasukkan nilai untuk nama produk baru.
  • SupplierID tidak.
  • CategoryID tidak.
  • QuantityPerUnit tambahkan TextBox, atur ID ke NewQuantityPerUnit.
  • UnitPrice tambahkan TextBox bernama NewUnitPrice dan CompareValidator yang memastikan nilai yang dimasukkan adalah nilai mata uang yang lebih besar dari atau sama dengan nol.
  • UnitsInStock gunakan TextBox yang ID telah diatur ke NewUnitsInStock. Sertakan CompareValidator yang memastikan bahwa nilai yang dimasukkan adalah nilai bilangan bulat yang lebih besar dari atau sama dengan nol.
  • UnitsOnOrder gunakan TextBox yang ID telah diatur ke NewUnitsOnOrder. Sertakan CompareValidator yang memastikan bahwa nilai yang dimasukkan adalah nilai bilangan bulat yang lebih besar dari atau sama dengan nol.
  • ReorderLevel gunakan TextBox yang ID telah diatur ke NewReorderLevel. Sertakan CompareValidator yang memastikan bahwa nilai yang dimasukkan adalah nilai bilangan bulat yang lebih besar dari atau sama dengan nol.
  • Discontinued tambahkan Kotak Centang, atur ID ke NewDiscontinued.
  • CategoryName tambahkan DropDownList dan atur ID ke NewCategoryID. Ikat ke ObjectDataSource baru bernama CategoriesDataSource dan konfigurasikan untuk menggunakan CategoriesBLL metode kelas s GetCategories() . Buat DropDownList s menampilkan bidang data ListItem, menggunakan CategoryName sebagai nilai mereka.
  • SupplierName tambahkan DropDownList dan atur ID ke NewSupplierID. Ikat ke ObjectDataSource baru bernama SuppliersDataSource dan konfigurasikan untuk menggunakan SuppliersBLL metode kelas s GetSuppliers() . Buat DropDownList s menampilkan bidang data ListItem, menggunakan CompanyName sebagai nilai mereka.

Untuk setiap kontrol validasi, bersihkan ForeColor properti sehingga FooterStyle warna latar depan putih kelas CSS akan digunakan sebagai pengganti merah default. Gunakan juga properti ErrorMessage untuk deskripsi terperinci, tetapi atur properti Text ke tanda bintang. Untuk mencegah teks kontrol validasi menyebabkan antarmuka penyisipan dibungkus menjadi dua baris, atur FooterStyle properti s Wrap ke false untuk masing-masing FooterTemplate yang menggunakan kontrol validasi. Terakhir, tambahkan kontrol ValidationSummary di bawah GridView dan atur propertinya ShowMessageBox ke true dan propertinya ShowSummary ke false.

Saat menambahkan produk baru, kita perlu menyediakan CategoryID dan SupplierID. Informasi ini diambil melalui DropDownLists di sel footer untuk CategoryName bidang dan SupplierName . Saya memilih untuk menggunakan bidang ini alih-alih CategoryID dan SupplierID TemplateFields karena di baris data dalam kisi, pengguna kemungkinan lebih tertarik untuk melihat kategori dan nama pemasok daripada nilai ID mereka. Karena nilai CategoryID dan SupplierID sekarang ditangkap di bidang CategoryName dan antarmuka penyisipan SupplierName, kita dapat menghapus TemplateFields CategoryID dan SupplierID dari GridView.

Demikian pula, ProductID tidak digunakan saat menambahkan produk baru, sehingga ProductID TemplateField juga dapat dihapus. Namun, mari kita biarkan ProductID kolom dalam kotak. Selain kontrol TextBoxes, DropDownLists, CheckBoxes, dan validasi yang membentuk antarmuka penyisipan, kita juga memerlukan tombol Tambahkan yang, ketika diklik, melakukan logika untuk menambahkan produk baru ke database. Di Langkah 4 kita akan menyertakan tombol Tambahkan di antarmuka penyisipan di ProductID TemplateFields FooterTemplate.

Jangan ragu untuk meningkatkan penampilan berbagai bidang GridView. Misalnya, Anda mungkin ingin memformat nilai UnitPrice sebagai mata uang, meratakan bidang UnitsInStock, UnitsOnOrder, dan ReorderLevel ke kanan, dan memperbarui nilai HeaderText untuk TemplateFields.

Setelah membuat berbagai antarmuka penyisipan di FooterTemplate s, menghapus SupplierID, dan CategoryID TemplateFields, serta meningkatkan tampilan kisi melalui pemformatan dan penyelarasan TemplateFields, markup deklaratif dari GridView akan menyerupai contoh berikut:

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    AllowPaging="True" EnableViewState="False" ShowFooter="True">
    <Columns>
        <asp:TemplateField HeaderText="ProductID" InsertVisible="False" 
            SortExpression="ProductID">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" 
                    Text='<%# Bind("ProductID") %>'></asp:Label>
            </ItemTemplate>
            <ItemStyle HorizontalAlign="Center" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" 
                    Text='<%# Bind("ProductName") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewProductName" runat="server"></asp:TextBox>
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                    runat="server" ControlToValidate="NewProductName"
                    Display="Dynamic"  ForeColor="
                    ErrorMessage="You must enter a name for the new product.">
                    * </asp:RequiredFieldValidator>
            </FooterTemplate>
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Category" SortExpression="CategoryName">
            <ItemTemplate>
                <asp:Label ID="Label10" runat="server" 
                    Text='<%# Bind("CategoryName") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:DropDownList ID="NewCategoryID" runat="server" 
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID">
                </asp:DropDownList>
                <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
                    OldValuesParameterFormatString="original_{0}" 
                    SelectMethod="GetCategories" TypeName="CategoriesBLL">
                </asp:ObjectDataSource>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Supplier" SortExpression="SupplierName">
            <ItemTemplate>
                <asp:Label ID="Label11" runat="server" 
                    Text='<%# Bind("SupplierName") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:DropDownList ID="NewSupplierID" runat="server" 
                    DataSourceID="SuppliersDataSource"
                    DataTextField="CompanyName" DataValueField="SupplierID">
                </asp:DropDownList><asp:ObjectDataSource ID="SuppliersDataSource" 
                    runat="server" OldValuesParameterFormatString="original_{0}" 
                    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
                </asp:ObjectDataSource>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Qty/Unit" SortExpression="QuantityPerUnit">
            <ItemTemplate>
                <asp:Label ID="Label5" runat="server" 
                    Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewQuantityPerUnit" runat="server"></asp:TextBox>
            </FooterTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
            <ItemTemplate>
                <asp:Label ID="Label6" runat="server" 
                    Text='<%# Bind("UnitPrice", "{0:c}") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                $<asp:TextBox ID="NewUnitPrice" runat="server" Columns="8" />
                <asp:CompareValidator ID="CompareValidator1" runat="server" 
                    ControlToValidate="NewUnitPrice"
                    ErrorMessage="You must enter a valid currency value greater than 
                        or equal to 0.00. Do not include the currency symbol."
                    ForeColor="" Operator="GreaterThanEqual" Type="Currency" 
                    ValueToCompare="0" Display="Dynamic">
                    * </asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Units In Stock" 
            SortExpression="Units In Stock">
            <ItemTemplate>
                <asp:Label ID="Label7" runat="server" 
                    Text='<%# Bind("UnitsInStock") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewUnitsInStock" runat="server" Columns="5" />
                <asp:CompareValidator ID="CompareValidator2" runat="server" 
                    ControlToValidate="NewUnitsInStock" Display="Dynamic" 
                    ErrorMessage="You must enter a valid numeric value for units 
                        in stock that's greater than or equal to zero."
                    ForeColor="" Operator="GreaterThanEqual" Type="Integer" 
                        ValueToCompare="0">*</asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Units On Order" SortExpression="UnitsOnOrder">
            <ItemTemplate>
                <asp:Label ID="Label8" runat="server" 
                    Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewUnitsOnOrder" runat="server" Columns="5" />
                <asp:CompareValidator ID="CompareValidator3" runat="server" 
                    ControlToValidate="NewUnitsOnOrder" Display="Dynamic" 
                    ErrorMessage="You must enter a valid numeric value for units on 
                        order that's greater than or equal to zero."
                    ForeColor="" Operator="GreaterThanEqual" Type="Integer" 
                    ValueToCompare="0">*</asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Reorder Level" SortExpression="ReorderLevel">
            <ItemTemplate>
                <asp:Label ID="Label9" runat="server" 
                    Text='<%# Bind("ReorderLevel") %>'></asp:Label>
            </ItemTemplate>
            <FooterTemplate>
                <asp:TextBox ID="NewReorderLevel" runat="server" Columns="5" />
                <asp:CompareValidator ID="CompareValidator4" runat="server" 
                    ControlToValidate="NewReorderLevel" Display="Dynamic" 
                    ErrorMessage="You must enter a valid numeric value for reorder 
                        level that's greater than or equal to zero."
                    ForeColor="" Operator="GreaterThanEqual" Type="Integer" 
                    ValueToCompare="0">*</asp:CompareValidator>
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <FooterStyle Wrap="False" />
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
            <ItemTemplate>
                <asp:CheckBox ID="CheckBox1" runat="server" 
                    Checked='<%# Bind("Discontinued") %>' Enabled="false" />
            </ItemTemplate>
            <FooterTemplate>
                <asp:CheckBox ID="NewDiscontinued" runat="server" />
            </FooterTemplate>
            <ItemStyle HorizontalAlign="Center" />
            <FooterStyle HorizontalAlign="Center" />
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Saat dilihat melalui browser, baris footer GridView sekarang menyertakan antarmuka penyisipan yang selesai (lihat Gambar 10). Pada titik ini, antarmuka penyisipan tidak menyertakan sarana bagi pengguna untuk menunjukkan bahwa dia memasukkan data untuk produk baru dan ingin menyisipkan rekaman baru ke dalam database. Selain itu, kita belum membahas bagaimana data yang dimasukkan ke dalam footer akan diterjemahkan ke dalam rekaman baru dalam Products database. Di Langkah 4 kita akan melihat cara menyertakan tombol Tambahkan ke antarmuka penyisipan dan cara menjalankan kode pada postback saat diklik. Langkah 5 memperlihatkan cara menyisipkan rekaman baru menggunakan data dari footer.

Footer GridView Menyediakan Antarmuka untuk Menambahkan Rekaman Baru

Gambar 10: Footer GridView Menyediakan Antarmuka untuk Menambahkan Rekaman Baru (Klik untuk melihat gambar ukuran penuh)

Langkah 4: Menyertakan Tombol Tambahkan di Antarmuka Penyisipan

Kita perlu menyertakan tombol Tambahkan di suatu tempat di antarmuka penyisipan karena antarmuka penyisipan baris footer saat ini tidak memiliki sarana bagi pengguna untuk menunjukkan bahwa mereka telah selesai memasukkan informasi produk baru. Ini dapat ditempatkan di salah satu kolom yang ada FooterTemplate atau kita dapat menambahkan kolom baru ke kisi untuk tujuan ini. Untuk tutorial ini, mari kita tempatkan tombol Tambahkan di ProductID TemplateFields FooterTemplate.

Dari Desainer, klik tautan Edit Templat di smart tag GridView dan kemudian pilih bidang ProductID dari daftar drop-down FooterTemplate. Tambahkan kontrol Web Tombol (atau LinkButton atau ImageButton, jika Anda mau) ke templat, atur ID-nya ke AddProduct, CommandName-nya ke Sisipkan, dan propertinya Text ke Tambahkan seperti yang ditunjukkan pada Gambar 11.

Tempatkan Tombol Tambahkan di FooterTemplate Bidang Templat ProductID

Gambar 11: Tempatkan Tombol Tambahkan di ProductID Bidang FooterTemplate Templat (Klik untuk melihat gambar ukuran penuh)

Setelah Anda menyertakan tombol Tambahkan, uji halaman di browser. Perhatikan bahwa saat mengklik tombol Tambahkan dengan data yang tidak valid di antarmuka penyisipan, postback disingkat dan kontrol ValidationSummary menunjukkan data yang tidak valid (lihat Gambar 12). Dengan data yang sesuai dimasukkan, mengklik tombol Tambahkan mengakibatkan permintaan balik. Namun, tidak ada catatan yang ditambahkan ke database. Kita perlu menulis sedikit kode untuk benar-benar melakukan penyisipan.

Postback Tombol Tambah diputus jika ada data yang tidak valid di antarmuka penyisipan data

Gambar 12: Postback Tombol Tambah Digagalkan jika Ada Data yang Tidak Valid di Antarmuka Penyisipan (Klik untuk melihat gambar ukuran penuh)

Nota

Kontrol validasi dalam antarmuka penyisipan tidak ditetapkan ke grup validasi. Ini berfungsi dengan baik selama antarmuka penyisipan adalah satu-satunya set kontrol validasi pada halaman. Namun, jika ada kontrol validasi lain di halaman (seperti kontrol validasi di antarmuka pengeditan kisi), kontrol validasi di antarmuka penyisipan dan properti Tambahkan tombol s ValidationGroup harus ditetapkan nilai yang sama sehingga untuk mengaitkan kontrol ini dengan grup validasi tertentu. Lihat Membedah Kontrol Validasi di ASP.NET 2.0 untuk informasi selengkapnya tentang pemartisian kontrol validasi dan tombol pada halaman ke dalam grup validasi.

Langkah 5: Menyisipkan Rekaman Baru KeProductsDalam Tabel

Saat menggunakan fitur pengeditan bawaan GridView, GridView secara otomatis menangani semua pekerjaan yang diperlukan untuk melakukan pembaruan. Secara khusus, ketika tombol Perbarui diklik, tombol tersebut menyalin nilai yang dimasukkan dari antarmuka pengeditan ke parameter dalam koleksi ObjectDataSource UpdateParameters dan memulai pembaruan dengan memanggil metode ObjectDataSource s Update() . Karena GridView tidak menyediakan fungsionalitas bawaan tersebut untuk menyisipkan, kita harus menerapkan kode yang memanggil metode ObjectDataSource s Insert() dan menyalin nilai dari antarmuka penyisipan ke koleksi ObjectDataSource InsertParameters .

Logika sisipkan ini harus dijalankan setelah tombol Tambahkan diklik. Seperti yang dibahas dalam tutorial Menambahkan dan Merespons Tombol dalam GridView, setiap kali Tombol, LinkButton, atau ImageButton dalam GridView diklik, peristiwa GridView RowCommand diaktifkan pada saat postback. Peristiwa ini dipicu ketika Tombol, LinkButton, atau ImageButton ditambahkan secara eksplisit seperti tombol Tambah di baris footer, atau ketika ditambahkan secara otomatis oleh GridView (misalnya, LinkButton di bagian atas setiap kolom saat fitur Pengurutan diaktifkan, atau LinkButton di antarmuka penomoran saat fitur Paging diaktifkan).

Oleh karena itu, untuk menanggapi pengguna yang mengklik tombol Tambahkan, kita perlu membuat penanganan aktivitas untuk peristiwa GridView RowCommand . Karena peristiwa ini diaktifkan setiap kali setiap tombol, LinkButton, atau ImageButton di GridView diklik, sangat penting bahwa kita hanya melanjutkan logika penyisipan jika properti CommandName yang diteruskan ke penghubung peristiwa tersebut sesuai dengan nilai CommandName tombol Tambahkan (Sisipkan). Selain itu, kita juga hanya boleh melanjutkan jika kontrol validasi melaporkan data yang valid. Untuk mengakomodasi hal ini, buat penangan acara untuk RowCommand event dengan kode berikut:

protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
    // Insert data if the CommandName == "Insert" 
    // and the validation controls indicate valid data...
    if (e.CommandName == "Insert" && Page.IsValid)
    {
        // TODO: Insert new record...
    }
}

Nota

Anda mungkin bertanya-tanya mengapa pengendali acara berusaha memeriksa properti Page.IsValid. Bagaimanapun, apakah postback tidak akan dihentikan jika data yang tidak valid dimasukkan melalui antarmuka penyisipan? Asumsi ini benar selama pengguna belum menonaktifkan JavaScript atau telah mengambil langkah-langkah untuk menghindari logika validasi sisi klien. Singkatnya, seseorang tidak boleh mengandalkan validasi sisi klien secara ketat; pemeriksaan sisi server untuk validitas harus selalu dilakukan sebelum bekerja dengan data.

Pada Langkah 1, kami membuat ProductsDataSource ObjectDataSource sehingga metode Insert() dipetakan ke metode ProductsBLL dari kelas AddProduct. Untuk menyisipkan rekaman baru ke Products dalam tabel, kita cukup memanggil metode ObjectDataSource:Insert()

protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
    // Insert data if the CommandName == "Insert" 
    // and the validation controls indicate valid data...
    if (e.CommandName == "Insert" && Page.IsValid)
    {
        // Insert new record
        ProductsDataSource.Insert();
    }
}

Sekarang setelah metode Insert() dipanggil, langkah berikutnya adalah menyalin nilai dari antarmuka penyisipan ke parameter yang diteruskan ke metode kelas ProductsBLLAddProduct. Seperti yang kita lihat kembali dalam tutorial Memeriksa Peristiwa yang Terkait dengan Menyisipkan, Memperbarui, dan Menghapus , ini dapat dicapai melalui peristiwa ObjectDataSource Inserting . Inserting Dalam kejadian tersebut, kita perlu merujuk kontrol dari baris footer Products GridView secara programatik dan menetapkan nilai-nilainya ke koleksi e.InputParameters. Jika pengguna menghilangkan nilai seperti membiarkan ReorderLevel TextBox kosong, kita perlu menentukan bahwa nilai yang dimasukkan ke dalam database harus NULL. Karena metode AddProducts menerima jenis nullable untuk bidang database yang nullable, cukup gunakan jenis nullable dan atur nilainya menjadi null jika masukan pengguna dihilangkan.

protected void ProductsDataSource_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{
    // Programmatically reference Web controls in the inserting interface...
    TextBox NewProductName = 
        (TextBox)Products.FooterRow.FindControl("NewProductName");
    DropDownList NewCategoryID = 
        (DropDownList)Products.FooterRow.FindControl("NewCategoryID");
    DropDownList NewSupplierID = 
        (DropDownList)Products.FooterRow.FindControl("NewSupplierID");
    TextBox NewQuantityPerUnit = 
        (TextBox)Products.FooterRow.FindControl("NewQuantityPerUnit");
    TextBox NewUnitPrice = 
        (TextBox)Products.FooterRow.FindControl("NewUnitPrice");
    TextBox NewUnitsInStock = 
        (TextBox)Products.FooterRow.FindControl("NewUnitsInStock");
    TextBox NewUnitsOnOrder = 
        (TextBox)Products.FooterRow.FindControl("NewUnitsOnOrder");
    TextBox NewReorderLevel = 
        (TextBox)Products.FooterRow.FindControl("NewReorderLevel");
    CheckBox NewDiscontinued = 
        (CheckBox)Products.FooterRow.FindControl("NewDiscontinued");
    // Set the ObjectDataSource's InsertParameters values...
    e.InputParameters["productName"] = NewProductName.Text;
    
    e.InputParameters["supplierID"] = 
        Convert.ToInt32(NewSupplierID.SelectedValue);
    e.InputParameters["categoryID"] = 
        Convert.ToInt32(NewCategoryID.SelectedValue);
    
    string quantityPerUnit = null;
    if (!string.IsNullOrEmpty(NewQuantityPerUnit.Text))
        quantityPerUnit = NewQuantityPerUnit.Text;
    e.InputParameters["quantityPerUnit"] = quantityPerUnit;
    decimal? unitPrice = null;
    if (!string.IsNullOrEmpty(NewUnitPrice.Text))
        unitPrice = Convert.ToDecimal(NewUnitPrice.Text);
    e.InputParameters["unitPrice"] = unitPrice;
    short? unitsInStock = null;
    if (!string.IsNullOrEmpty(NewUnitsInStock.Text))
        unitsInStock = Convert.ToInt16(NewUnitsInStock.Text);
    e.InputParameters["unitsInStock"] = unitsInStock;
    short? unitsOnOrder = null;
    if (!string.IsNullOrEmpty(NewUnitsOnOrder.Text))
        unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text);
    e.InputParameters["unitsOnOrder"] = unitsOnOrder;
    short? reorderLevel = null;
    if (!string.IsNullOrEmpty(NewReorderLevel.Text))
        reorderLevel = Convert.ToInt16(NewReorderLevel.Text);
    e.InputParameters["reorderLevel"] = reorderLevel;
    
    e.InputParameters["discontinued"] = NewDiscontinued.Checked;
}

Dengan penangan kejadian Inserting diselesaikan, entri baru dapat ditambahkan ke tabel database Products melalui baris footer GridView. Lanjutkan dan coba tambahkan beberapa produk baru.

Meningkatkan dan Menyesuaikan Operasi Penambahan

Saat ini, mengklik tombol Tambahkan menambahkan rekaman baru ke tabel database tetapi tidak memberikan umpan balik visual apa pun bahwa rekaman telah berhasil ditambahkan. Idealnya, kotak kontrol Web Label atau pemberitahuan sisi klien akan memberi tahu pengguna bahwa penyisipan mereka telah selesai dengan sukses. Saya meninggalkan ini sebagai latihan untuk pembaca.

GridView yang digunakan dalam tutorial ini tidak menerapkan urutan pengurutan apa pun ke produk yang tercantum, juga tidak memungkinkan pengguna akhir untuk mengurutkan data. Akibatnya, rekaman diurutkan dalam database berdasarkan bidang kunci utamanya. Karena setiap rekaman baru memiliki nilai yang ProductID lebih besar dari yang sebelumnya, setiap kali produk baru ditambahkan, ia ditempatkan di akhir grid. Oleh karena itu, Anda mungkin ingin mengirim pengguna secara otomatis ke halaman terakhir GridView setelah menambahkan rekaman baru. Ini dapat dicapai dengan menambahkan baris kode berikut setelah panggilan ke ProductsDataSource.Insert() di RowCommand penanganan aktivitas untuk menunjukkan bahwa pengguna perlu dikirim ke halaman terakhir setelah mengikat data ke GridView:

// Indicate that the user needs to be sent to the last page
SendUserToLastPage = true;

SendUserToLastPage adalah variabel Boolean tingkat halaman yang awalnya diberi nilai false. Di pengendali peristiwa GridView DataBound, jika SendUserToLastPage bernilai salah, properti PageIndex diperbarui untuk mengarahkan pengguna ke halaman terakhir.

protected void Products_DataBound(object sender, EventArgs e)
{
    // Send user to last page of data, if needed
    if (SendUserToLastPage)
        Products.PageIndex = Products.PageCount - 1;
}

Alasan properti PageIndex diatur dalam penangan acara DataBound (tidak pada penangan acara RowCommand) adalah karena ketika penangan acara RowCommand diaktifkan, kami belum menambahkan rekaman baru ke tabel basis data Products. Oleh karena itu, dalam penanganan kejadian RowCommand indeks halaman terakhir (PageCount - 1) merupakan indeks halaman terakhir sebelum produk baru ditambahkan. Untuk sebagian besar produk yang ditambahkan, indeks halaman terakhir sama setelah menambahkan produk baru. Tetapi ketika produk yang ditambahkan menghasilkan indeks halaman terakhir baru, jika kami salah memperbarui PageIndex di RowCommand penanganan aktivitas, maka kita akan dibawa ke halaman kedua hingga terakhir (indeks halaman terakhir sebelum menambahkan produk baru) dibandingkan dengan indeks halaman terakhir yang baru. DataBound Karena penanganan peristiwa berlangsung setelah produk baru ditambahkan dan data dimuat ulang ke tabel, dengan menetapkan properti di PageIndex, kita tahu indeks halaman terakhir yang benar telah diperoleh.

Akhirnya, GridView yang digunakan dalam tutorial ini cukup luas karena jumlah bidang yang harus dikumpulkan untuk menambahkan produk baru. Karena lebar ini, tata letak vertikal DetailsView mungkin lebih disukai. Lebar keseluruhan GridView dapat dikurangi dengan mengumpulkan lebih sedikit input. Mungkin kita tidak perlu mengumpulkan bidang UnitsOnOrder, UnitsInStock, dan ReorderLevel saat menambahkan produk baru, dalam hal ini kolom ini dapat dihapus dari GridView.

Untuk menyesuaikan data yang dikumpulkan, kita dapat menggunakan salah satu dari dua pendekatan:

  • Lanjutkan menggunakan metode AddProduct yang mengharapkan nilai untuk bidang UnitsOnOrder, UnitsInStock, dan ReorderLevel. Dalam penanganan acara Inserting, berikan nilai default berupa hard-coded untuk digunakan pada input yang telah dihapus dari antarmuka penyisipan.
  • Buat overload baru metode AddProduct pada kelas ProductsBLL yang tidak menerima input untuk bidang UnitsOnOrder, UnitsInStock, dan ReorderLevel. Kemudian, di halaman ASP.NET, konfigurasikan ObjectDataSource untuk menggunakan kelebihan beban baru ini.

Kedua opsi akan berfungsi sama baiknya. Dalam tutorial sebelumnya, kami menggunakan opsi terakhir, membuat beberapa overloading untuk metode kelas ProductsBLLUpdateProduct.

Ringkasan

GridView tidak memiliki kemampuan penyisipan bawaan yang ditemukan di DetailsView dan FormView, tetapi dengan sedikit upaya, antarmuka penyisipan dapat ditambahkan ke baris footer. Untuk menampilkan baris footer di GridView cukup atur propertinya ShowFooter ke true. Konten baris footer dapat dikustomisasi untuk setiap bidang dengan mengonversi bidang ke TemplateField dan menambahkan antarmuka penyisipan ke FooterTemplate. Seperti yang kita lihat dalam tutorial ini, FooterTemplate dapat berisi Tombol, Kotak Teks, Daftar DropDown, Kotak Centang, kontrol sumber data untuk mengisi kontrol Web berbasis data (seperti DropDownLists), dan kontrol validasi. Bersama dengan kontrol untuk mengumpulkan input pengguna, Tombol Tambahkan, LinkButton, atau ImageButton diperlukan.

Saat tombol Tambahkan diklik, metode ObjectDataSource s Insert() dipanggil untuk memulai alur kerja penyisipan. ObjectDataSource kemudian akan memanggil metode sisipkan yang dikonfigurasi ProductsBLL (metode kelas AddProduct dalam tutorial ini). Kita harus menyalin nilai dari antarmuka penyisipan GridView ke koleksi ObjectDataSource sebelum InsertParameters metode sisipkan dipanggil. Ini dapat dicapai dengan mereferensikan kontrol Web pada antarmuka penyisipan secara terprogram di penanganan peristiwa ObjectDataSource Inserting.

Tutorial ini melengkapi ulasan kami tentang teknik untuk meningkatkan tampilan GridView. Set tutorial berikutnya akan memeriksa cara bekerja dengan data biner seperti gambar, PDF, dokumen Word, dan sebagainya dan kontrol Web data.

Selamat Pemrograman!

Tentang Penulis

Scott Mitchell, penulis tujuh buku ASP/ASP.NET dan pendiri 4GuysFromRolla.com, telah bekerja sama dengan teknologi Microsoft Web sejak 1998. Scott bekerja sebagai konsultan, pelatih, dan penulis independen. Buku terbarunya adalah Sams Teach Yourself ASP.NET 2.0 dalam 24 Jam. Dia dapat dijangkau di mitchell@4GuysFromRolla.com.

Ucapan terima kasih khusus kepada

Seri tutorial ini ditinjau oleh banyak peninjau yang bermanfaat. Peninjau utama untuk tutorial ini adalah Bernadette Leigh. Tertarik untuk meninjau artikel MSDN saya yang akan datang? Jika demikian, hubungi saya di mitchell@4GuysFromRolla.com.