Udostępnij za pośrednictwem


Wstawianie nowego rekordu w stopce kontrolki GridView (VB)

Autor: Scott Mitchell

Pobierz plik PDF

Chociaż kontrolka GridView nie zapewnia wbudowanej obsługi wstawiania nowego rekordu danych, w tym samouczku pokazano, jak rozszerzyć element 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 funkcje modyfikacji danych. W przypadku korzystania z deklaratywnych kontrolek ź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 jednego 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ć element 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 (Pole tekstowe dla nazwy produktu, Lista rozwijana 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.

Wiersz stopki zawiera interfejs dodawania nowych produktów

Rysunek 1. Wiersz stopki zawiera interfejs dodawania nowych produktów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 1. Wyświetlanie informacji o produkcie w siatceView

Zanim zaczniemy się martwić o utworzenie interfejsu wstawiania w stopce GridView, najpierw skoncentrujmy się na dodaniu elementu GridView do strony zawierającej listę produktów w bazie danych. Zacznij od otwarcia InsertThroughFooter.aspx strony w EnhancedGridView folderze i przeciągnij element GridView z przybornika do Projektant, ustawiając właściwość GridView ID na Products. Następnie użyj tagu inteligentnego GridView, aby powiązać go z nowym obiektem ObjectDataSource o nazwie ProductsDataSource.

Tworzenie nowego obiektuDataSource o nazwie ProductsDataSource

Rysunek 2. Utwórz nową nazwę ObjectDataSource o nazwie ProductsDataSource (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Skonfiguruj obiekt ObjectDataSource, aby użyć ProductsBLL metody s GetProducts() klasy w celu pobrania informacji o produkcie. Na potrzeby tego samouczka skoncentrujmy się ściśle na dodawaniu funkcji wstawiania i nie martwimy 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 wartość (Brak) .

Mapuj metodę AddProduct na metodę ObjectDataSource s Insert()

Rysunek 3. Mapowanie metody na metodę AddProduct ObjectDataSource Insert() (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Ustaw Drop-Down Listy kart UPDATE i DELETE na wartość (Brak)

Rysunek 4. Ustawianie kart UPDATE i DELETE Drop-Down Listy na (Brak) (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy Kreatora konfigurowania ź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ć aż 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>

Wszystkie pola danych produktu są wyświetlane w stronicowanym elemecie GridView

Rysunek 5. Wszystkie pola danych produktu są wyświetlane w stronicowanym widoku GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)

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 GridView s ShowHeader i ShowFooter . Aby wyświetlić wiersz stopki, po prostu ustaw ShowFooter właściwość na True. Jak pokazano na rysunku 6, ustawienie ShowFooter właściwości w celu True dodawania wiersza stopki do siatki.

Aby wyświetlić wiersz stopki, ustaw wartość ShowFooter na true

Rysunek 6. Aby wyświetlić wiersz stopki, ustaw ShowFooter na True (kliknij, aby wyświetlić obraz pełnowymiarowy)

Należy pamiętać, ż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 korzystała FooterStyle z klasy CSS. Klasa jest definiowana FooterStyle w Styles.css następujący sposób:

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

Uwaga

Zapoznaliśmy się z użyciem wiersza stopki GridView w poprzednich samouczkach. W razie potrzeby zapoznaj się z samouczkiem Wyświetlanie informacji o podsumowaniu w stopce elementu GridView , aby zapoznać się z odświeżaniem.

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.

Pusty wiersz stopki jest wyświetlany powyżej kontrolek interfejsu stronicowania

Rysunek 7. Pusty wiersz stopki jest wyświetlany nad kontrolkami interfejsu stronicowania (kliknij, aby wyświetlić obraz pełnowymiarowy)

W samouczku Using TemplateFields (Używanie pól szablonów w kontrolce GridView ) pokazano, jak znacznie dostosować wyświetlanie określonej kolumny GridView przy użyciu pól TemplateFields (w przeciwieństwie do elementów BoundFields lub CheckBoxFields); w dostosowywaniu interfejsu modyfikacji danych przyjrzeliśmy się użyciu pola szablonów w celu dostosowania interfejsu edycji w elemecie GridView. Pamiętaj, że pole szablonu 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. Element ItemTemplate, na 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 EditItemTemplatepole TemplateField zawiera FooterTemplate również element określający zawartość wiersza stopki. W związku z tym możemy dodać kontrolki sieci Web potrzebne dla każdego wstawiania interfejsu pola do elementu FooterTemplate. Aby rozpocząć, przekonwertuj wszystkie pola w elemecie 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.

Konwertowanie każdego pola 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 element TemplateField z elementem ItemTemplate zawierającym etykietę, która wyświetla odpowiednie pole danych i EditItemTemplate wyświetla pole danych w polu TextBox. Pole ProductName powiązane 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 pole Discontinued CheckBoxField zostało przekonwertowane na pole szablonu, którego ItemTemplate i EditItemTemplate zawiera kontrolkę sieci Web CheckBox (z wyłączoną ItemTemplate kontrolką CheckBox). Pole powiązane tylko do ProductID odczytu zostało przekonwertowane na pole szablonu z kontrolką Etykieta zarówno w elemecie , jak ItemTemplate i EditItemTemplate. Krótko mówiąc, konwertowanie istniejącego pola GridView na pole TemplateField jest szybkim i łatwym sposobem przełączania się do bardziej dostosowywanego pola TemplateField bez utraty żadnej z istniejących funkcji pola.

Ponieważ funkcja GridView, z którymi pracujemy, nie obsługuje edycji, możesz usunąć element EditItemTemplate z każdego pola szablonu ItemTemplate, pozostawiając tylko element . Po wykonaniu tej czynności znacznik deklaratywnej kontrolki 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 (ProductIDna przykład); inne będą się różnić w kontrolkach sieci Web używanych do zbierania nowych informacji o produkcie.

Aby utworzyć interfejs edycji, wybierz link Edytuj szablony z tagu inteligentnego GridView. Następnie z listy rozwijanej wybierz odpowiednie pole s FooterTemplate i przeciągnij odpowiednią kontrolkę z przybornika na Projektant.

Dodawanie odpowiedniego interfejsu wstawiania do stopki każdego polaTemplate

Rysunek 9. Dodawanie odpowiedniego interfejsu wstawiania do poszczególnych pól FooterTemplate (kliknij, aby wyświetlić obraz pełnowymiarowy)

Poniższa lista punktowana wylicza pola GridView, określając interfejs wstawiania do dodania:

  • ProductID Brak.
  • ProductName dodaj pole TextBox i ustaw jego ID wartość na NewProductName. Dodaj kontrolkę RequiredFieldValidator, aby upewnić się, że użytkownik wprowadza wartość nazwy nowego produktu.
  • SupplierID Brak.
  • CategoryID Brak.
  • QuantityPerUnit dodaj pole TextBox, ustawiając jego ID wartość na NewQuantityPerUnit.
  • UnitPrice dodaj pole TextBox o nazwie NewUnitPrice i element CompareValidator, który gwarantuje, że wprowadzona wartość jest wartością waluty większą lub równą zero.
  • UnitsInStock użyj pola TextBox, którego ID ustawiono wartość NewUnitsInStock. Dołącz moduł CompareValidator, który gwarantuje, że wprowadzona wartość jest wartością całkowitą większą lub równą zero.
  • UnitsOnOrder użyj pola TextBox, którego ID ustawiono wartość NewUnitsOnOrder. Dołącz moduł CompareValidator, który gwarantuje, że wprowadzona wartość jest wartością całkowitą większą lub równą zero.
  • ReorderLevel użyj pola TextBox, którego ID ustawiono wartość NewReorderLevel. Dołącz moduł CompareValidator, który gwarantuje, że wprowadzona wartość jest wartością całkowitą większą lub równą zero.
  • Discontinued dodaj pole wyboru, ustawiając wartość IDNewDiscontinuedna .
  • CategoryName dodaj listę DropDownList i ustaw ją ID na NewCategoryID. Powiąż ją z nową usługą ObjectDataSource o nazwie CategoriesDataSource i skonfiguruj ją tak, aby korzystała CategoriesBLL z metody klasy s GetCategories() . Czy lista DropDownList s ListItem wyświetla CategoryName pole danych przy użyciu CategoryID pola danych jako ich wartości.
  • SupplierName dodaj listę DropDownList i ustaw ją ID na NewSupplierID. Powiąż ją z nową usługą ObjectDataSource o nazwie SuppliersDataSource i skonfiguruj ją tak, aby korzystała SuppliersBLL z metody klasy s GetSuppliers() . Czy lista DropDownList s ListItem wyświetla CompanyName pole danych przy użyciu SupplierID pola danych jako ich 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. Użyj również właściwości w ErrorMessage celu uzyskania szczegółowego opisu, ale ustaw Text właściwość na gwiazdkę. Aby zapobiec spowodowaniu zawijania interfejsu wstawiania do dwóch wierszy kontrolki walidacji, 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 pod kontrolką GridView i ustaw jej ShowMessageBox właściwość na True i jej ShowSummary właściwość na False.

Podczas dodawania nowego produktu musimy podać element CategoryID i SupplierID. Te informacje są przechwytywane za pośrednictwem list rozwijanych 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 i SupplierID TemplateFields, ponieważ w wierszach danych siatki użytkownik prawdopodobnie bardziej interesuje się 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ąć CategoryID pola i z SupplierID kontrolki GridView.

Podobnie ProductID element 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 tworzących interfejs wstawiania będziemy również potrzebować przycisku Dodaj, który po kliknięciu wykonuje logikę dodawania do bazy danych. W kroku 4 dołączymy przycisk Dodaj w interfejsie wstawiania w elemecie ProductID TemplateField s FooterTemplate.

Możesz poprawić wygląd różnych pól GridView. Na przykład możesz sformatować UnitPrice wartości jako walutę, wyrównać prawym przyciskiem UnitsInStockdo pól , UnitsOnOrderi ReorderLevel oraz zaktualizować HeaderText wartości pola TemplateFields.

Po utworzeniu mnóstwa interfejsów wstawiania w FooterTemplate s, usunięciu SupplierIDpól i CategoryID szablonów oraz poprawie estetyki siatki za pomocą formatowania i wyrównania pól TemplateFields deklaratywny znacznik 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 w przeglądarce wiersz stopki 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 musimy jeszcze rozwiązać 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. Krok 5 pokazuje, jak wstawić nowy rekord przy użyciu danych z stopki.

Stopka GridView udostępnia interfejs dodawania nowego rekordu

Rysunek 10. Stopka GridView udostępnia interfejs dodawania nowego rekordu (kliknij, aby wyświetlić obraz pełnowymiarowy)

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 one ukończone, wprowadzając nowe informacje o 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 z FooterTemplate listy rozwijanej. Dodaj kontrolkę Sieci Web przycisku (lub LinkButton lub ImageButton, jeśli wolisz) do szablonu, ustawiając jego identyfikator na AddProduct, CommandName na Wstaw, a jej Text właściwość na Dodaj, jak pokazano na rysunku 11.

Umieść przycisk Dodaj w stopce ProductID TemplateField sTemplate

Rysunek 11. Umieść przycisk Dodaj w polach ProductID szablonów FooterTemplate (kliknij, aby wyświetlić obraz pełnowymiarowy)

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 następuje zwarcie zwrotne, a kontrolka ValidationSummary wskazuje nieprawidłowe dane (patrz Rysunek 12). Po wprowadzeniu odpowiednich danych kliknięcie przycisku Dodaj powoduje powrót. Żaden rekord nie jest jednak dodawany do bazy danych. Musimy napisać trochę kodu, aby rzeczywiście wykonać wstawianie.

Postback przycisku Dodaj jest zwarcie, jeśli w interfejsie wstawiania istnieją nieprawidłowe dane

Rysunek 12. Powrót po awarii przycisku dodaj jest zwarty, jeśli w interfejsie wstawiania znajdują się nieprawidłowe dane (kliknij, aby wyświetlić obraz pełnowymiarowy)

Uwaga

Kontrolki walidacji w interfejsie wstawiania nie zostały przypisane do grupy walidacji. Działa to prawidłowo, tak długo, jak interfejs wstawiania jest jedynym zestawem kontrolek walidacji 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. Aby uzyskać więcej informacji na temat partycjonowania kontrolek walidacji na stronie w grupach weryfikacji, zobacz Dissecting the Validation Controls in ASP.NET 2.0 (Rozłączanie kontrolek weryfikacji w ASP.NET 2.0 ).

Krok 5. Wstawianie nowego rekorduProductsdo tabeli

W przypadku korzystania z wbudowanych funkcji edycji elementu GridView funkcja GridView automatycznie obsługuje całą pracę niezbędną do przeprowadzenia aktualizacji. W szczególności po kliknięciu przycisku Aktualizuj kopiuje wartości wprowadzone z interfejsu edycji do parametrów w kolekcji ObjectDataSource i uruchamia aktualizację, wywołując metodę ObjectDataSourceUpdateParameters.Update() Ponieważ funkcja GridView nie udostępnia takich wbudowanych funkcji 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 i odpowiadanie na przyciski w elemecie GridView, w dowolnym momencie kliknięcie przycisku, elementu LinkButton lub elementu ImageButton w siatceview, zdarzenie GridView RowCommand zostanie wyzwolone po powrocie zwrotne. 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 (na przykład 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ęty dowolny przycisk Button, LinkButton lub ImageButton w elemecie GridView, 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 również kontynuować tylko wtedy, gdy kontrole weryfikacji zgłaszają prawidłowe dane. Aby to uwzględnić, utwórz procedurę obsługi zdarzeń dla RowCommand zdarzenia przy użyciu następującego kodu:

Protected Sub Products_RowCommand(sender As Object, e As GridViewCommandEventArgs) _
    Handles Products.RowCommand
    
    ' Insert data if the CommandName == "Insert" 
    ' and the validation controls indicate valid data...
    If e.CommandName = "Insert" AndAlso Page.IsValid Then
        ' TODO: Insert new record...
    End If
End Sub

Uwaga

Być może zastanawiasz się, dlaczego program obsługi zdarzeń przeszkadza sprawdzanie Page.IsValid właściwości. Po tym wszystkim nie będzie pomijany po powrocie zwrotnym, 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; przed rozpoczęciem pracy z danymi należy zawsze wykonać sprawdzanie poprawności po stronie serwera.

W kroku 1 utworzyliśmy obiekt ObjectDataSource, ProductsDataSource tak aby jego Insert() metoda została zamapowana na metodę ProductsBLL s AddProduct klasy. Aby wstawić nowy rekord do Products tabeli, możemy po prostu wywołać metodę ObjectDataSource Insert() :

Protected Sub Products_RowCommand(sender As Object, e As GridViewCommandEventArgs) _
    Handles Products.RowCommand
    
    ' Insert data if the CommandName == "Insert" 
    ' and the validation controls indicate valid data...
    If e.CommandName = "Insert" AndAlso Page.IsValid Then
        ' Insert new record
        ProductsDataSource.Insert()
    End If
End Sub

Insert() Po wywołaniu metody wszystkie pozostałe elementy to skopiowanie wartości z interfejsu wstawiania do parametrów przekazanych do ProductsBLL metody klasy.AddProduct Jak widzieliśmy już w samouczku Badanie zdarzeń skojarzonych z wstawianiem, aktualizowaniem i usuwaniem , można to zrobić za pośrednictwem zdarzenia ObjectDataSource Inserting . Inserting W przypadku, gdy musimy programowo odwołać się do kontrolek z Products wiersza stopki GridView i przypisać ich wartości do e.InputParameters kolekcji. Jeśli użytkownik pomija wartość, taką jak pozostawienie pola Tekstowego pustego ReorderLevel , musimy określić, że wartość wstawiona do bazy danych powinna mieć wartość NULL. AddProducts Ponieważ metoda akceptuje typy dopuszczane wartości null dla pól bazy danych z możliwością wartości null, wystarczy użyć typu dopuszczalnego wartości null i ustawić jej wartość na Nothing w przypadku, gdy dane wejściowe użytkownika są pomijane.

Protected Sub ProductsDataSource_Inserting _
    (sender As Object, e As .ObjectDataSourceMethodEventArgs) _
    Handles ProductsDataSource.Inserting
    
    ' Programmatically reference Web controls in the inserting interface...
    Dim NewProductName As TextBox = _
        Products.FooterRow.FindControl("NewProductName")
    Dim NewCategoryID As DropDownList = _
        Products.FooterRow.FindControl("NewCategoryID")
    Dim NewSupplierID As DropDownList = _
        Products.FooterRow.FindControl("NewSupplierID")
    Dim NewQuantityPerUnit As TextBox = _
        Products.FooterRow.FindControl("NewQuantityPerUnit")
    Dim NewUnitPrice As TextBox = _
        Products.FooterRow.FindControl("NewUnitPrice")
    Dim NewUnitsInStock As TextBox = _
        Products.FooterRow.FindControl("NewUnitsInStock")
    Dim NewUnitsOnOrder As TextBox = _
        Products.FooterRow.FindControl("NewUnitsOnOrder")
    Dim NewReorderLevel As TextBox = _
        Products.FooterRow.FindControl("NewReorderLevel")
    Dim NewDiscontinued As 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)
    Dim quantityPerUnit As String = Nothing
    If Not String.IsNullOrEmpty(NewQuantityPerUnit.Text) Then
        quantityPerUnit = NewQuantityPerUnit.Text
    End If
    e.InputParameters("quantityPerUnit") = quantityPerUnit
    Dim unitPrice As Nullable(Of Decimal) = Nothing
    If Not String.IsNullOrEmpty(NewUnitPrice.Text) Then
        unitPrice = Convert.ToDecimal(NewUnitPrice.Text)
    End If
    e.InputParameters("unitPrice") = unitPrice
    Dim unitsInStock As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewUnitsInStock.Text) Then
        unitsInStock = Convert.ToInt16(NewUnitsInStock.Text)
    End If
    e.InputParameters("unitsInStock") = unitsInStock
    Dim unitsOnOrder As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewUnitsOnOrder.Text) Then
        unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text)
    End If
    e.InputParameters("unitsOnOrder") = unitsOnOrder
    Dim reorderLevel As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewReorderLevel.Text) Then
        reorderLevel = Convert.ToInt16(NewReorderLevel.Text)
    End If
    e.InputParameters("reorderLevel") = reorderLevel
    e.InputParameters("discontinued") = NewDiscontinued.Checked
End Sub

Po zakończeniu Inserting obsługi zdarzeń nowe rekordy można dodać do Products tabeli bazy danych za pośrednictwem wiersza stopki GridView. Przejdź do przodu 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 żadnej wizualnej opinii, że rekord został pomyślnie dodany. W idealnym przypadku kontrolka sieci Web etykiety lub pole alertu po stronie klienta informuje użytkownika o pomyślnym zakończeniu wstawiania. Zostawię to jako ćwiczenie dla czytelnika.

Element 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 tak, jak znajdują się w bazie danych według ich pola klucza podstawowego. Ponieważ każdy nowy rekord ma ProductID wartość większą niż ostatni, za każdym razem, gdy dodawany jest nowy produkt, jest on naklejany na końcu siatki. W związku z tym możesz automatycznie wysłać użytkownika do ostatniej strony elementu GridView po dodaniu nowego rekordu. Można to zrobić, dodając następujący wiersz kodu po wywołaniu metody ProductsDataSource.Insert() w RowCommand programie obsługi zdarzeń, aby wskazać, że użytkownik musi zostać wysłany na ostatnią stronę po powiązaniu danych z kontrolką GridView:

' Indicate that the user needs to be sent to the last page
SendUserToLastPage = True

SendUserToLastPageto zmienna logiczna na poziomie strony, która początkowo ma przypisaną wartość .False W procedurze obsługi zdarzeń usługi GridView DataBound , jeśli SendUserToLastPage jest to fałsz, właściwość zostanie zaktualizowana, PageIndex aby wysłać użytkownika do ostatniej strony.

Protected Sub Products_DataBound(sender As Object, e As EventArgs) _
    Handles Products.DataBound
    
    ' Send user to last page of data, if needed
    If SendUserToLastPage Then
        Products.PageIndex = Products.PageCount - 1
    End If
End Sub

Powodem, PageIndex dla którego właściwość jest ustawiona w DataBound procedurze 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 dodanych produktów ostatni indeks strony jest taki sam po dodaniu nowego produktu. Jednak 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 (ostatni indeks strony przed dodaniem nowego produktu) w przeciwieństwie do nowego indeksu ostatniej strony. DataBound Ponieważ program obsługi zdarzeń jest uruchamiany po dodaniu nowego produktu i odbiciu danych do siatki, ustawiając PageIndex tam 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 elementu DetailsView. Ogólną szerokość kontrolki GridView można zmniejszyć, zbierając mniej danych wejściowych. Być może nie musimy zbierać UnitsOnOrderpól , UnitsInStocki 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 metod:

  • Kontynuuj korzystanie z AddProduct metody, która oczekuje wartości dla UnitsOnOrderpól , UnitsInStocki ReorderLevel . W procedurze Inserting obsługi zdarzeń podaj trwale zakodowane wartości domyślne do użycia dla tych danych wejściowych, które zostały usunięte z interfejsu wstawiania.
  • Utwórz nowe przeciążenie AddProduct metody w ProductsBLL klasie, która nie akceptuje danych wejściowych dla UnitsOnOrderpól , UnitsInStocki ReorderLevel . Następnie na stronie ASP.NET skonfiguruj obiekt ObjectDataSource do używania tego nowego przeciążenia.

Każda z opcji 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 UpdateProduct .

Podsumowanie

Kontrolka GridView nie ma wbudowanych funkcji wstawiania znalezionych w kontrolkach DetailsView i FormView, ale przy odrobinie wysiłku można dodać interfejs wstawiania do wiersza stopki. Aby wyświetlić wiersz stopki w obiekcie GridView, po prostu ustaw jego ShowFooter właściwość na Truewartość . Zawartość wiersza stopki można dostosować dla każdego pola, konwertując pole na wartość TemplateField i dodając interfejs wstawiania do obiektu FooterTemplate. Jak pokazano w tym samouczku, FooterTemplate element może zawierać kontrolki Buttons, TextBoxes, DropDownLists, CheckBoxes, źródła danych służące do wypełniania kontrolek sieci Web opartych na danych (takich jak DropDownLists) i kontrolek weryfikacji. Oprócz kontrolek do zbierania danych wejściowych użytkownika potrzebny jest przycisk dodawania, przycisk LinkButton lub imageButton.

Po kliknięciu przycisku Dodaj wywoływana Insert() jest metoda ObjectDataSource, aby rozpocząć wstawianie przepływu pracy. Następnie obiekt ObjectDataSource wywoła skonfigurowaną metodę insert ( ProductsBLL metodę klasy s AddProduct w tym samouczku). Przed wywołaniem metody inserting należy skopiować wartości z interfejsu wstawiania kontrolki GridView do kolekcji ObjectDataSource InsertParameters . Można to osiągnąć przez programowe odwoływanie się do wstawiania kontrolek sieci Web interfejsu w procedurze obsługi zdarzeń obiektu Inserting ObjectDataSource.

W tym samouczku przedstawiono techniki ulepszania wyglądu obiektu GridView. W następnym zestawie samouczków dowiesz się, jak pracować z danymi binarnymi, takimi jak obrazy, pliki PDF, Word dokumenty itd., oraz 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 przejrzyona przez wielu przydatnych recenzentów. Głównym recenzentem tego samouczka był Bernadette Leigh. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresemmitchell@4GuysFromRolla.com .