Wstawianie nowego rekordu w stopce kontrolki GridView (C#)
Autor : Scott Mitchell
Chociaż kontrolka GridView nie zapewnia wbudowanej obsługi wstawiania nowego rekordu danych, w tym samouczku przedstawiono sposób rozszerzania kontrolki GridView w celu uwzględnienia interfejsu wstawiania.
Wprowadzenie
Zgodnie z opisem w samouczku Omówienie wstawiania, aktualizowania i usuwania danych kontrolki GridView, DetailsView i FormView w sieci Web obejmują wbudowane możliwości modyfikacji danych. W przypadku używania z deklaratywnymi kontrolkami źródła danych te trzy kontrolki sieci Web można szybko i łatwo skonfigurować do modyfikowania danych — i w scenariuszach bez konieczności pisania pojedynczego wiersza kodu. Niestety tylko kontrolki DetailsView i FormView zapewniają wbudowane funkcje wstawiania, edytowania i usuwania. Obiekt GridView oferuje tylko obsługę edytowania i usuwania. Jednak przy odrobinie smaru łokcia możemy rozszerzyć GridView, aby uwzględnić interfejs wstawiania.
Dodając możliwości wstawiania do kontrolki GridView, odpowiadamy za podjęcie decyzji o sposobie dodawania nowych rekordów, tworzeniu interfejsu wstawiania i pisaniu kodu w celu wstawienia nowego rekordu. W tym samouczku przyjrzymy się dodaniu interfejsu wstawiania do wiersza stopki kontrolki GridView (zobacz Rysunek 1). Komórka stopki dla każdej kolumny zawiera odpowiedni element interfejsu użytkownika zbierania danych (TextBox dla nazwy produktu, DropDownList dla dostawcy itd.). Potrzebujemy również kolumny przycisku Dodaj, który po kliknięciu spowoduje powrót i wstawi nowy rekord do Products
tabeli przy użyciu wartości podanych w wierszu stopki.
Rysunek 1. Wiersz stopki zawiera interfejs dodawania nowych produktów (kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Krok 1. Wyświetlanie informacji o produkcie w siatceView
Zanim zaczniemy się martwić o utworzenie interfejsu wstawiania w stopce kontrolki GridView, najpierw skoncentrujmy się na dodaniu kontrolki GridView do strony zawierającej listę produktów w bazie danych. Zacznij od otwarcia InsertThroughFooter.aspx
strony w folderze EnhancedGridView
i przeciągnięcia kontrolki GridView z przybornika do Projektant, ustawiając właściwość GridView ID
na Products
wartość . Następnie użyj tagu inteligentnego GridView, aby powiązać go z nowym obiektem ObjectDataSource o nazwie ProductsDataSource
.
Rysunek 2. Tworzenie nowego obiektuDataSource o nazwie ProductsDataSource
(kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Skonfiguruj obiekt ObjectDataSource do pobierania informacji o produkcie przy ProductsBLL
użyciu metody s GetProducts()
klasy . W tym samouczku skoncentrujmy się ściśle na dodawaniu funkcji wstawiania i nie martwmy się o edytowanie i usuwanie. W związku z tym upewnij się, że lista rozwijana na karcie INSERT jest ustawiona AddProduct()
na i że listy rozwijane na kartach UPDATE i DELETE są ustawione na (Brak) .
Rysunek 3. Mapowanie AddProduct
metody na metodę ObjectDataSource Insert()
(kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Rysunek 4. Ustawianie kart UPDATE i DELETE Drop-Down Listy na (Brak) (kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Po zakończeniu pracy kreatora Konfigurowanie źródła danych objectDataSource program Visual Studio automatycznie doda pola do kontrolki GridView dla każdego z odpowiednich pól danych. Na razie pozostaw wszystkie pola dodane przez program Visual Studio. W dalszej części tego samouczka wrócimy i usuniemy niektóre pola, których wartości nie muszą być określone podczas dodawania nowego rekordu.
Ponieważ w bazie danych znajduje się blisko 80 produktów, użytkownik będzie musiał przewijać całą dół do dołu strony internetowej, aby dodać nowy rekord. W związku z tym włączmy stronicowanie, aby interfejs wstawiania był bardziej widoczny i dostępny. Aby włączyć stronicowanie, zaznacz pole wyboru Włącz stronicowanie z tagu inteligentnego GridView.
Na tym etapie znaczniki deklaratywne gridView i ObjectDataSource powinny wyglądać podobnie do następujących:
<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>
Rysunek 5. Wszystkie pola danych produktu są wyświetlane w stronicowanym kącie GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 2. Dodawanie wiersza stopki
Wraz z nagłówkiem i wierszami danych element GridView zawiera wiersz stopki. Wiersze nagłówka i stopki są wyświetlane w zależności od wartości właściwości i ShowFooter
gridViewShowHeader
. Aby wyświetlić wiersz stopki, po prostu ustaw ShowFooter
właściwość na true
wartość . Jak pokazano na rysunku 6, ustawienie właściwości w ShowFooter
celu true
dodawania wiersza stopki do siatki.
Rysunek 6. Aby wyświetlić wiersz stopki, ustaw ShowFooter
na True
(kliknij, aby wyświetlić obraz pełnowymiarowy)
Zwróć uwagę, że wiersz stopki ma ciemnoczerwony kolor tła. Jest to spowodowane utworzonym motywem DataWebControls i zastosowanym do wszystkich stron z powrotem w samouczku Wyświetlanie danych za pomocą obiektuDataSource . W szczególności GridView.skin
plik konfiguruje FooterStyle
właściwość tak, aby używała FooterStyle
klasy CSS. Klasa jest zdefiniowana FooterStyle
w Styles.css
następujący sposób:
.FooterStyle
{
background-color: #a33;
color: White;
text-align: right;
}
Uwaga
W poprzednich samouczkach zapoznaliśmy się z użyciem wiersza stopki kontrolki GridView. W razie potrzeby zapoznaj się z samouczkiem Wyświetlanie informacji podsumowania w stopce kontrolki GridView w celu odświeżenia.
Po ustawieniu ShowFooter
właściwości na true
, poświęć chwilę, aby wyświetlić dane wyjściowe w przeglądarce. Obecnie wiersz stopki nie zawiera żadnych kontrolek tekstowych ani internetowych. W kroku 3 zmodyfikujemy stopkę dla każdego pola GridView, tak aby zawierała odpowiedni interfejs wstawiania.
Rysunek 7. Pusty wiersz stopki jest wyświetlany powyżej kontrolek interfejsu stronicowania (kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Krok 3. Dostosowywanie wiersza stopki
W samouczku Dotyczącym używania pól szablonów w kontrolce GridView pokazano, jak znacznie dostosować wyświetlanie określonej kolumny GridView przy użyciu kontrolek TemplateFields (w przeciwieństwie do pól BoundFields lub CheckBoxFields); W dostosowywaniu interfejsu modyfikacji danych przyjrzeliśmy się używaniu elementu TemplateFields w celu dostosowania interfejsu edycji w elementy GridView. Pamiętaj, że pole templatefield składa się z wielu szablonów, które definiują kombinację znaczników, kontrolek sieci Web i składni powiązania danych używanych dla niektórych typów wierszy. Na ItemTemplate
przykład , określa szablon używany dla wierszy tylko do odczytu, podczas gdy EditItemTemplate
definiuje szablon dla edytowalnego wiersza.
Wraz z elementami ItemTemplate
i EditItemTemplate
element TemplateField zawiera również element FooterTemplate
, który określa zawartość wiersza stopki. W związku z tym możemy dodać kontrolki sieci Web potrzebne dla każdego pola interfejsu wstawiania do elementu FooterTemplate
. Aby rozpocząć, przekonwertuj wszystkie pola w elementy GridView na TemplateFields. Można to zrobić, klikając link Edytuj kolumny w tagu inteligentnym GridView, wybierając każde pole w lewym dolnym rogu, a następnie klikając link Konwertuj to pole na pole szablonu.
Rysunek 8. Konwertowanie każdego pola na pole szablonu
Kliknięcie pola Konwertuj to pole na pole szablonu powoduje przekształcenie bieżącego typu pola w równoważne pole szablonu. Na przykład każde pole BoundField jest zastępowane przez pole TemplateField elementem ItemTemplate
zawierającym etykietę, która wyświetla odpowiednie pole danych i EditItemTemplate
wyświetla pole danych w polu tekstowym. Pole ProductName
boundfield zostało przekonwertowane na następujące znaczniki TemplateField:
<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>
Podobnie Discontinued
pole CheckBoxField zostało przekonwertowane na pole szablonu, którego ItemTemplate
i EditItemTemplate
zawiera kontrolkę internetową CheckBox (z wyłączonym ItemTemplate
polem kontrolnym). Pole BoundField tylko ProductID
do odczytu zostało przekonwertowane na pole szablonu z kontrolką Etykieta zarówno w kontrolce , jak ItemTemplate
i EditItemTemplate
. Krótko mówiąc, konwertowanie istniejącego pola GridView na pole TemplateField to szybki i łatwy sposób przełączania się na bardziej dostosowywalne pole TemplateField bez utraty żadnej funkcji istniejącego pola.
Ponieważ element GridView, z który pracujemy, nie obsługuje edycji, możesz usunąć element EditItemTemplate
z każdego pola szablonu, pozostawiając tylko element ItemTemplate
. Po wykonaniu tej czynności znacznik deklaratywny gridView powinien wyglądać następująco:
<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>
Teraz, gdy każde pole GridView zostało przekonwertowane na pole szablonu, możemy wprowadzić odpowiedni interfejs wstawiania do każdego pola s FooterTemplate
. Niektóre pola nie będą miały interfejsu wstawiania (ProductID
na przykład); inne będą się różnić w kontrolkach sieci Web używanych do zbierania informacji o nowym produkcie.
Aby utworzyć interfejs edycji, wybierz link Edytuj szablony z tagu inteligentnego GridView. Następnie z listy rozwijanej wybierz odpowiednie pola FooterTemplate
i przeciągnij odpowiednią kontrolkę z przybornika na Projektant.
Rysunek 9. Dodawanie odpowiedniego interfejsu wstawiania do każdego pola FooterTemplate
(kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Poniższa lista punktowana wylicza pola GridView, określając interfejs wstawiania do dodania:
ProductID
Brak.ProductName
dodaj kontrolkę TextBox i ustaw jejID
wartość naNewProductName
. Dodaj również kontrolkę RequiredFieldValidator, aby upewnić się, że użytkownik wprowadzi wartość dla nazwy nowego produktu.SupplierID
Brak.CategoryID
Brak.QuantityPerUnit
dodaj kontrolkę TextBox, ustawiając jejID
wartość naNewQuantityPerUnit
.UnitPrice
Dodaj element TextBox o nazwieNewUnitPrice
i element CompareValidator, który zapewnia, że wprowadzona wartość jest wartością waluty większą lub równą zero.UnitsInStock
użyj kontrolki TextBox, którejID
parametr ma ustawioną wartośćNewUnitsInStock
. Uwzględnij moduł CompareValidator, który gwarantuje, że wprowadzona wartość jest liczbą całkowitą większą lub równą zero.UnitsOnOrder
użyj kontrolki TextBox, którejID
parametr ma ustawioną wartośćNewUnitsOnOrder
. Uwzględnij moduł CompareValidator, który gwarantuje, że wprowadzona wartość jest liczbą całkowitą większą lub równą zero.ReorderLevel
użyj kontrolki TextBox, którejID
parametr ma ustawioną wartośćNewReorderLevel
. Uwzględnij moduł CompareValidator, który gwarantuje, że wprowadzona wartość jest liczbą całkowitą większą lub równą zero.Discontinued
dodaj kontrolkę CheckBox, ustawiając jejID
wartość naNewDiscontinued
.CategoryName
dodaj listę DropDownList i ustaw jąID
naNewCategoryID
. Powiąż go z nową klasą ObjectDataSource o nazwieCategoriesDataSource
i skonfiguruj ją tak, aby korzystałaCategoriesBLL
z metody klasy sGetCategories()
. Wyświetl pole danych zaCategoryName
pomocą pola danych z listy DropDownListListItem
, używającCategoryID
pola danych jako wartości.SupplierName
dodaj listę DropDownList i ustaw jąID
naNewSupplierID
. Powiąż go z nową klasą ObjectDataSource o nazwieSuppliersDataSource
i skonfiguruj ją tak, aby korzystałaSuppliersBLL
z metody klasy sGetSuppliers()
. Wyświetl pole danych zaCompanyName
pomocą pola danych z listy DropDownListListItem
, używającSupplierID
pola danych jako wartości.
Dla każdej kontrolki walidacji usuń ForeColor
zaznaczenie właściwości, tak aby FooterStyle
biały kolor pierwszego planu klasy CSS był używany zamiast domyślnego czerwonego koloru. Należy również użyć ErrorMessage
właściwości w celu uzyskania szczegółowego opisu, ale ustaw Text
właściwość na gwiazdkę. Aby zapobiec tworzeniu tekstu kontrolki sprawdzania poprawności powodującym zawijanie interfejsu wstawiania do dwóch wierszy, ustaw FooterStyle
właściwość s Wrap
na wartość false dla każdego z FooterTemplate
elementów, które używają kontrolki walidacji. Na koniec dodaj kontrolkę ValidationSummary poniżej kontrolki GridView i ustaw jej ShowMessageBox
właściwość na true
i jej ShowSummary
właściwość na false
.
Podczas dodawania nowego produktu musimy podać elementy CategoryID
i SupplierID
. Te informacje są przechwytywane za pośrednictwem listy DropDownLists w komórkach stopki dla CategoryName
pól i SupplierName
. Zdecydowałem się używać tych pól w przeciwieństwie do CategoryID
pól szablonów i SupplierID
, ponieważ w wierszach danych siatki użytkownik jest prawdopodobnie bardziej zainteresowany wyświetlaniem kategorii i nazw dostawców, a nie ich wartości identyfikatorów. CategoryID
Ponieważ wartości i SupplierID
są teraz przechwytywane w CategoryName
interfejsach wstawiania pól iSupplierName
, możemy usunąć pola CategoryID
i SupplierID
z obiektu GridView.
Podobnie element ProductID
nie jest używany podczas dodawania nowego produktu, więc pole szablonu ProductID
można również usunąć. Pozostawmy ProductID
jednak pole w siatce. Oprócz kontrolek TextBoxes, DropDownLists, CheckBoxes i validation, które tworzą interfejs wstawiania, potrzebujemy również przycisku Dodaj, który po kliknięciu wykonuje logikę dodawania nowego produktu do bazy danych. W kroku 4 dołączymy przycisk Dodaj do interfejsu wstawiania w elemecie ProductID
TemplateField.FooterTemplate
Możesz poprawić wygląd różnych pól GridView. Możesz na przykład sformatować UnitPrice
wartości jako walutę, wyrównać UnitsInStock
do prawej pola , UnitsOnOrder
i ReorderLevel
oraz zaktualizować HeaderText
wartości pól TemplateFields.
Po utworzeniu mnóstwa wstawień interfejsów w FooterTemplate
s, usunięciu SupplierID
pól szablonów i CategoryID
i poprawie estetyki siatki poprzez formatowanie i wyrównanie pól TemplateFields, znacznik deklaratywny GridView powinien wyglądać podobnie do następującego:
<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>
Po wyświetleniu za pośrednictwem przeglądarki wiersz stopki kontrolki GridView zawiera teraz ukończony interfejs wstawiania (zobacz Rysunek 10). W tym momencie interfejs wstawiania nie zawiera środków dla użytkownika, aby wskazać, że wprowadziła dane dla nowego produktu i chce wstawić nowy rekord do bazy danych. Ponadto mamy jeszcze do uwzględnienia sposób, w jaki dane wprowadzone w stopce przełożą się na nowy rekord w Products
bazie danych. W kroku 4 przyjrzymy się, jak dołączyć przycisk Dodaj do interfejsu wstawiania i jak wykonać kod po kliknięciu po kliknięciu. Krok 5 pokazuje, jak wstawić nowy rekord przy użyciu danych z stopki.
Rysunek 10. Stopka GridView udostępnia interfejs dodawania nowego rekordu (kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Krok 4. Dołączenie przycisku Dodaj w interfejsie wstawiania
Musimy dołączyć przycisk Dodaj gdzieś w interfejsie wstawiania, ponieważ interfejs wstawiania wierszy stopki obecnie nie ma środków dla użytkownika, aby wskazać, że zostały ukończone wprowadzanie informacji o nowym produkcie. Można to umieścić w jednym z istniejących FooterTemplate
elementów lub dodać nową kolumnę do siatki w tym celu. W tym samouczku umieśćmy przycisk Dodaj w elemecie ProductID
TemplateField s FooterTemplate
.
W Projektant kliknij link Edytuj szablony w tagu inteligentnym GridView, a następnie wybierz ProductID
pole FooterTemplate
z listy rozwijanej. Dodaj kontrolkę Sieci Web przycisku (lub LinkButton lub ImageButton, jeśli wolisz) do szablonu, ustawiając jego identyfikator na AddProduct
, na CommandName
Wstaw, a jej Text
właściwość na Dodaj, jak pokazano na rysunku 11.
Rysunek 11. Umieść przycisk Dodaj w polach ProductID
szablonów FooterTemplate
(kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Po dołączeniu przycisku Dodaj przetestuj stronę w przeglądarce. Należy pamiętać, że po kliknięciu przycisku Dodaj z nieprawidłowymi danymi w interfejsie wstawiania ogłaszanie zwrotne jest zwarcie, a kontrolka ValidationSummary wskazuje nieprawidłowe dane (zobacz Rysunek 12). Po wprowadzeniu odpowiednich danych kliknięcie przycisku Dodaj powoduje ogłaszanie zwrotne. Do bazy danych nie jest jednak dodawany żaden rekord. Musimy napisać trochę kodu, aby rzeczywiście wykonać operację wstawiania.
Rysunek 12. Ogłaszanie zwrotne przycisku dodawania jest zwarcie, jeśli w interfejsie wstawiania znajdują się nieprawidłowe dane (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Uwaga
Kontrolki sprawdzania poprawności w interfejsie wstawiania nie zostały przypisane do grupy sprawdzania poprawności. Działa to poprawnie, o ile interfejs wstawiania jest jedynym zestawem kontrolek sprawdzania poprawności na stronie. Jeśli jednak na stronie znajdują się inne kontrolki weryfikacji (takie jak kontrolki walidacji w interfejsie edycji siatki), kontrolki walidacji w interfejsie wstawiania i Dodaj właściwości przycisku ValidationGroup
powinny mieć przypisaną tę samą wartość, aby skojarzyć te kontrolki z określoną grupą walidacji. Zobacz Artykuł Dissecting the Validation Controls in ASP.NET 2.0 (Rozłączanie kontrolek weryfikacji w programie ASP.NET 2.0 ), aby uzyskać więcej informacji na temat partycjonowania kontrolek i przycisków weryfikacji na stronie w grupach weryfikacji.
Krok 5. Wstawianie nowego rekordu doProducts
tabeli
W przypadku korzystania z wbudowanych funkcji edycji kontrolki GridView funkcja GridView automatycznie obsługuje całą pracę niezbędną do przeprowadzenia aktualizacji. W szczególności kliknięcie przycisku Aktualizuj powoduje skopiowanie wartości wprowadzonych z interfejsu edycji do parametrów w kolekcji ObjectDataSource UpdateParameters
i rozpoczęcie aktualizacji przez wywołanie metody ObjectDataSource Update()
. Ponieważ kontrolka GridView nie udostępnia takich wbudowanych funkcji do wstawiania, musimy zaimplementować kod, który wywołuje metodę ObjectDataSource i Insert()
kopiuje wartości z interfejsu wstawiania do kolekcji ObjectDataSource InsertParameters
.
Ta logika wstawiania powinna zostać wykonana po kliknięciu przycisku Dodaj. Zgodnie z opisem w samouczku Dodawanie przycisków i odpowiadanie na nie w siatce, w dowolnym momencie kliknięcie przycisku, elementu LinkButton lub elementu ImageButton w siatce, zdarzenie GridView RowCommand
zostanie wyzwolone po ogłaszaniu zwrotnym. To zdarzenie jest wyzwalane, czy przycisk Button, LinkButton lub ImageButton został dodany jawnie, na przykład przycisk Dodaj w wierszu stopki lub jeśli został automatycznie dodany przez kontrolkę GridView (np. LinkButtons w górnej części każdej kolumny po wybraniu opcji Włącz sortowanie lub linkButtons w interfejsie stronicowania po wybraniu opcji Włącz stronicowanie).
W związku z tym, aby odpowiedzieć użytkownikowi klikając przycisk Dodaj, musimy utworzyć procedurę obsługi zdarzeń dla zdarzenia GridView RowCommand
. Ponieważ to zdarzenie jest uruchamiane za każdym razem, gdy zostanie kliknięto dowolny przycisk Button, LinkButton lub ImageButton w siatceView, ważne jest, aby kontynuować tylko logikę wstawiania, jeśli CommandName
właściwość przekazana do programu obsługi zdarzeń jest mapowana na CommandName
wartość przycisku Dodaj ( Wstaw ). Ponadto należy kontynuować tylko wtedy, gdy kontrolki weryfikacji zgłaszają prawidłowe dane. Aby to uwzględnić, utwórz program obsługi zdarzeń dla RowCommand
zdarzenia przy użyciu następującego kodu:
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...
}
}
Uwaga
Być może zastanawiasz się, dlaczego program obsługi zdarzeń przeszkadza sprawdzanie Page.IsValid
właściwości. Po tym wszystkim, czy ogłaszanie zwrotne nie zostanie pominięte, jeśli w interfejsie wstawiania podano nieprawidłowe dane? To założenie jest poprawne, o ile użytkownik nie wyłączył języka JavaScript lub podjął kroki w celu obejścia logiki weryfikacji po stronie klienta. Krótko mówiąc, nigdy nie należy polegać ściśle na weryfikacji po stronie klienta; sprawdzanie poprawności po stronie serwera powinno być zawsze wykonywane przed rozpoczęciem pracy z danymi.
W kroku 1 utworzyliśmy ProductsDataSource
obiekt ObjectDataSource, tak aby jego Insert()
metoda została zamapowana na metodę ProductsBLL
klasy s AddProduct
. Aby wstawić nowy rekord do Products
tabeli, możemy po prostu wywołać metodę 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();
}
}
Teraz, gdy Insert()
metoda została wywołana, pozostaje skopiować wartości z interfejsu wstawiania do parametrów przekazanych do ProductsBLL
metody klasy AddProduct
. Jak widzieliśmy w samouczku Badanie zdarzeń skojarzonych z wstawianiem, aktualizowaniem i usuwaniem , można to zrobić za pomocą zdarzenia ObjectDataSource Inserting
. Inserting
W przypadku, gdy musimy programowo odwołać się do kontrolek z Products
wiersza stopki kontrolki GridView i przypisać ich wartości do e.InputParameters
kolekcji. Jeśli użytkownik pominie wartość, taką jak pozostawienie pola TextBox pustego ReorderLevel
, musimy określić, że wartość wstawiona do bazy danych powinna mieć wartość NULL
. AddProducts
Ponieważ metoda akceptuje typy dopuszczane do wartości null dla pól bazy danych dopuszczalnych wartości null, po prostu użyj typu dopuszczalnego wartości null i ustaw jej wartość na null
w przypadku pominięcia danych wejściowych użytkownika.
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;
}
Po zakończeniu Inserting
obsługi zdarzeń można dodać nowe rekordy do Products
tabeli bazy danych za pośrednictwem wiersza stopki kontrolki GridView. Przejdź dalej i spróbuj dodać kilka nowych produktów.
Ulepszanie i dostosowywanie operacji dodawania
Obecnie kliknięcie przycisku Dodaj powoduje dodanie nowego rekordu do tabeli bazy danych, ale nie udostępnia żadnych wizualnych opinii, które rekord został pomyślnie dodany. W idealnym przypadku kontrolka Sieci Web etykiety lub pole alertu po stronie klienta informuje użytkownika, że jego wstawianie zakończyło się pomyślnie. Zostawię to jako ćwiczenie dla czytelnika.
Obiekt GridView używany w tym samouczku nie stosuje żadnej kolejności sortowania do wymienionych produktów ani nie zezwala użytkownikowi końcowemu na sortowanie danych. W związku z tym rekordy są uporządkowane zgodnie z ich polem klucza podstawowego w bazie danych. Ponieważ każdy nowy rekord ma ProductID
wartość większą niż ostatni, za każdym razem, gdy nowy produkt jest dodawany, jest on na końcu siatki. W związku z tym możesz automatycznie wysłać użytkownika do ostatniej strony obiektu GridView po dodaniu nowego rekordu. Można to zrobić, dodając następujący wiersz kodu po wywołaniu metody ProductsDataSource.Insert()
w procedurze obsługi zdarzeń, RowCommand
aby wskazać, że użytkownik musi zostać wysłany do ostatniej strony po powiązaniu danych z kontrolką GridView:
// Indicate that the user needs to be sent to the last page
SendUserToLastPage = true;
SendUserToLastPage
to zmienna logiczna na poziomie strony, która początkowo ma przypisaną wartość false
. W procedurze obsługi zdarzeń kontrolki DataBound
GridView, jeśli SendUserToLastPage
ma wartość false, właściwość zostanie zaktualizowana w PageIndex
celu wysłania użytkownika do ostatniej strony.
protected void Products_DataBound(object sender, EventArgs e)
{
// Send user to last page of data, if needed
if (SendUserToLastPage)
Products.PageIndex = Products.PageCount - 1;
}
Przyczyną PageIndex
ustawienia właściwości w procedurze DataBound
obsługi zdarzeń (w przeciwieństwie do RowCommand
programu obsługi zdarzeń) jest to, że gdy RowCommand
program obsługi zdarzeń uruchomi jeszcze nowy rekord do Products
tabeli bazy danych. W związku z tym w procedurze obsługi zdarzeń RowCommand
ostatni indeks strony (PageCount - 1
) reprezentuje ostatni indeks strony przed dodaniu nowego produktu. W przypadku większości dodawanych produktów ostatni indeks strony jest taki sam po dodaniu nowego produktu. Ale gdy dodany produkt spowoduje wyświetlenie nowego indeksu ostatniej strony, jeśli niepoprawnie zaktualizujemy PageIndex
element w RowCommand
procedurze obsługi zdarzeń, nastąpi przekierowanie do drugiej do ostatniej strony (indeks ostatniej strony przed dodaniem nowego produktu) w przeciwieństwie do nowego indeksu ostatniej strony. DataBound
Ponieważ procedura obsługi zdarzeń jest uruchamiana po dodaniu nowego produktu i odbiciu danych do siatki, ustawiając PageIndex
właściwość , wiemy, że otrzymujemy prawidłowy indeks ostatniej strony.
Na koniec element GridView używany w tym samouczku jest dość szeroki ze względu na liczbę pól, które należy zebrać w celu dodania nowego produktu. Ze względu na tę szerokość preferowany może być układ pionowy kontrolki DetailsView. Ogólną szerokość obiektu GridView można zmniejszyć, zbierając mniej danych wejściowych. Być może nie musimy zbierać UnitsOnOrder
pól , UnitsInStock
i ReorderLevel
podczas dodawania nowego produktu, w tym przypadku te pola można usunąć z widoku GridView.
Aby dostosować zebrane dane, możemy użyć jednego z dwóch podejść:
- Kontynuuj korzystanie z
AddProduct
metody, która oczekuje wartości dlaUnitsOnOrder
pól ,UnitsInStock
iReorderLevel
. W procedurze obsługi zdarzeńInserting
podaj zakodowane wartości domyślne, które mają być używane dla tych danych wejściowych, które zostały usunięte z interfejsu wstawiania. - Utwórz nowe przeciążenie
AddProduct
metody wProductsBLL
klasie, która nie akceptuje danych wejściowych dlaUnitsOnOrder
pól ,UnitsInStock
iReorderLevel
. Następnie na stronie ASP.NET skonfiguruj obiekt ObjectDataSource do używania tego nowego przeciążenia.
Każda opcja również będzie działać równie dobrze. W poprzednich samouczkach użyliśmy tej drugiej opcji, tworząc wiele przeciążeń dla ProductsBLL
metody klasy s UpdateProduct
.
Podsumowanie
Element GridView nie ma wbudowanych funkcji wstawiania znajdujących się w widoku DetailsView i FormView, ale z odrobiną wysiłku można dodać interfejs wstawiania do wiersza stopki. Aby wyświetlić wiersz stopki w elemecie GridView, po prostu ustaw jej ShowFooter
właściwość na true
. Zawartość wiersza stopki można dostosować dla każdego pola, konwertując pole na wartość TemplateField i dodając interfejs wstawiania do elementu FooterTemplate
. Jak pokazano w tym samouczku, FooterTemplate
może zawierać kontrolki Buttons, TextBoxes, DropDownLists, CheckBoxes, data source controls for populating data-driven Web controls (takie jak DropDownLists) i kontrolek walidacji. Oprócz kontrolek do zbierania danych wejściowych użytkownika jest wymagany przycisk Dodaj, LinkButton lub ImageButton.
Po kliknięciu przycisku Dodaj wywoływana jest metoda ObjectDataSource Insert()
, aby rozpocząć wstawianie przepływu pracy. Następnie obiekt ObjectDataSource wywoła skonfigurowaną metodę insert ( ProductsBLL
metodę klasy s AddProduct
w tym samouczku). Musimy skopiować wartości z interfejsu wstawiania elementu GridView do kolekcji ObjectDataSource InsertParameters
przed wywołaniem metody insert. Można to osiągnąć przez programowe odwoływanie się do wstawiania kontrolek sieci Web interfejsu w programie obsługi zdarzeń objectDataSource Inserting
.
W tym samouczku przedstawiono techniki ulepszania wyglądu elementu GridView. Następny zestaw samouczków sprawdzi, jak pracować z danymi binarnymi, takimi jak obrazy, pliki PDF, Word dokumenty itd. i kontrolki sieci Web danych.
Szczęśliwe programowanie!
Informacje o autorze
Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.
Specjalne podziękowania
Ta seria samouczków została sprawdzona przez wielu pomocnych recenzentów. Główny recenzent tego samouczka był Bernadette Leigh. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.