Personalizzazione dell'interfaccia di modifica di DataList (C#)

di Scott Mitchell

Scarica il PDF

In questa esercitazione verrà creata un'interfaccia di modifica più avanzata per DataList, una che include DropDownLists e checkBox.

Introduzione

I controlli Markup e Web in DataList EditItemTemplate definiscono la relativa interfaccia modificabile. In tutti gli esempi di DataList modificabili esaminati finora, l'interfaccia modificabile è stata costituita da controlli Web TextBox. Nell'esercitazione precedente è stata migliorata l'esperienza utente in fase di modifica aggiungendo controlli di convalida.

Può EditItemTemplate essere ulteriormente espanso per includere controlli Web diversi da TextBox, ad esempio DropDownLists, RadioButtonLists, Calendari e così via. Come per TextBoxes, quando si personalizza l'interfaccia di modifica per includere altri controlli Web, seguire questa procedura:

  1. Aggiungere il controllo Web a EditItemTemplate.
  2. Utilizzare la sintassi databinding per assegnare il valore del campo dati corrispondente alla proprietà appropriata.
  3. UpdateCommand Nel gestore eventi accedere al valore del controllo Web a livello di codice e passarlo al metodo BLL appropriato.

In questa esercitazione verrà creata un'interfaccia di modifica più avanzata per DataList, una che include DropDownLists e checkBox. In particolare, verrà creato un oggetto DataList che elenca le informazioni sul prodotto e consente l'aggiornamento del nome, del fornitore, della categoria e dello stato di interruzione del prodotto (vedere la figura 1).

L'interfaccia di modifica include un controllo TextBox, due elenchi a discesa e un controllo CheckBox

Figura 1: L'interfaccia di modifica include una casella di testo, due elenchi a discesa e un controllo CheckBox (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 1: Visualizzazione delle informazioni sul prodotto

Prima di poter creare l'interfaccia modificabile di DataList, è prima necessario compilare l'interfaccia di sola lettura. Per iniziare, aprire la CustomizedUI.aspx pagina dalla EditDeleteDataList cartella e, dal Designer, aggiungere un oggetto DataList alla pagina, impostandone ID la proprietà su Products. Dallo smart tag di DataList creare un nuovo ObjectDataSource. Denominare il nuovo ObjectDataSource ProductsDataSource e configurarlo per recuperare i dati dal ProductsBLL metodo della GetProducts classe. Come per le esercitazioni di DataList modificabili precedenti, le informazioni sul prodotto modificate verranno aggiornate passando direttamente al livello della logica di business. Di conseguenza, impostare gli elenchi a discesa nelle schede UPDATE, INSERT e DELETE su (Nessuno).

Impostare le schede UPDATE, INSERT e DELETE Drop-Down Elenchi su (Nessuna)

Figura 2: Impostare le schede UPDATE, INSERT e DELETE Drop-Down Elenchi su (Nessuna) (Fare clic per visualizzare l'immagine a dimensione intera)

Dopo aver configurato ObjectDataSource, Visual Studio creerà un valore predefinito ItemTemplate per DataList che elenca il nome e il valore per ognuno dei campi dati restituiti. Modificare in ItemTemplate modo che il modello elenchi il nome del prodotto in un <h4> elemento insieme al nome della categoria, al nome del fornitore, al prezzo e allo stato sospeso. Aggiungere inoltre un pulsante Modifica, assicurandosi che la relativa CommandName proprietà sia impostata su Modifica. Il markup dichiarativo per il codice ItemTemplate seguente:

<ItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="CategoryNameLabel" runat="server"
                    Text='<%# Eval("CategoryName") %>' />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="SupplierNameLabel" runat="server"
                    Text='<%# Eval("SupplierName") %>' />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="DiscontinuedLabel" runat="server"
                    Text='<%# Eval("Discontinued") %>' />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="EditButton"
                    Text="Edit" CommandName="Edit" />
            </td>
        </tr>
    </table>
    <br />
</ItemTemplate>

Il markup precedente illustra le informazioni sul prodotto usando un'intestazione <h4> per il nome del prodotto e una quattro colonne <table> per i campi rimanenti. Le ProductPropertyLabel classi CSS e ProductPropertyValue , definite in Styles.css, sono state descritte nelle esercitazioni precedenti. La figura 3 mostra lo stato di avanzamento quando viene visualizzato tramite un browser.

Viene visualizzato il nome, il fornitore, la categoria, lo stato sospeso e il prezzo di ogni prodotto

Figura 3: Viene visualizzato il nome, il fornitore, la categoria, lo stato sospeso e il prezzo di ogni prodotto (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 2: Aggiunta dei controlli Web all'interfaccia di modifica

Il primo passaggio per la creazione dell'interfaccia di modifica DataList personalizzata consiste nell'aggiungere i controlli Web necessari all'oggetto EditItemTemplate. In particolare, è necessario un oggetto DropDownList per la categoria, un altro per il fornitore e un controllo CheckBox per lo stato sospeso. Poiché il prezzo del prodotto non è modificabile in questo esempio, è possibile continuare a visualizzarlo usando un controllo Web Etichetta.

Per personalizzare l'interfaccia di modifica, fare clic sul collegamento Modifica modelli dallo smart tag di DataList e scegliere l'opzione EditItemTemplate nell'elenco a discesa. Aggiungere un oggetto DropDownList a EditItemTemplate e impostarlo ID su Categories.

Aggiungere un elenco a discesa per le categorie

Figura 4: Aggiungere un elenco a discesa per le categorie (fare clic per visualizzare l'immagine a dimensione intera)

Successivamente, dallo smart tag DropDownList s selezionare l'opzione Scegli origine dati e creare un nuovo ObjectDataSource denominato CategoriesDataSource. Configurare objectDataSource per l'uso del metodo della GetCategories() classe (vedere la CategoriesBLL figura 5). Successivamente, la Configurazione guidata origine dati dropDownList richiede che i campi dati vengano usati per ogni ListItem proprietà Text e Value . Fare in modo che DropDownList visualizzi il CategoryName campo dati e usi CategoryID come valore, come illustrato nella figura 6.

Creare un nuovo oggettoDataSource denominato CategoriesDataSource

Figura 5: Creare un nuovo oggettoDataSource denominato CategoriesDataSource (fare clic per visualizzare l'immagine a dimensione intera)

Configurare i campi visualizzazione e valore di DropDownList

Figura 6: Configurare i campi visualizzazione e valore dell'elenco a discesa (fare clic per visualizzare l'immagine a dimensione intera)

Ripetere questa serie di passaggi per creare un oggetto DropDownList per i fornitori. Impostare per l'oggetto ID DropDownList Suppliers su e denominarne ObjectDataSource SuppliersDataSource.

Dopo aver aggiunto i due DropDownList, aggiungere un controllo CheckBox per lo stato sospeso e un controllo TextBox per il nome del prodotto. Impostare i ID valori per CheckBox e TextBox rispettivamente su Discontinued e ProductName. Aggiungere un RequiredFieldValidator per assicurarsi che l'utente fornisca un valore per il nome del prodotto.

Infine, aggiungere i pulsanti Aggiorna e Annulla. Tenere presente che per questi due pulsanti è imperativo che le relative CommandName proprietà siano impostate rispettivamente su Update e Cancel.

È possibile disporre l'interfaccia di modifica, tuttavia si preferisce. Ho scelto di usare lo stesso layout a quattro colonne <table> dall'interfaccia di sola lettura, come illustrato nella sintassi dichiarativa e nella schermata seguente:

<EditItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Name:</td>
            <td colspan="3" class="ProductPropertyValue">
                <asp:TextBox runat="server" ID="ProductName" Width="90%" />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
                    ControlToValidate="ProductName"
                    ErrorMessage="You must enter a name for the product."
                    runat="server">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Categories" runat="server"
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID" />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Suppliers" DataTextField="CompanyName"
                    DataSourceID="SuppliersDataSource"
                    DataValueField="SupplierID" runat="server" />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:CheckBox runat="server" id="Discontinued" />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="UpdateButton" CommandName="Update"
                    Text="Update" />
                 
                <asp:Button runat="Server" ID="CancelButton" CommandName="Cancel"
                    Text="Cancel" CausesValidation="False" />
            </td>
        </tr>
    </table>
    <br />
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
        TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers"
        TypeName="SuppliersBLL">
    </asp:ObjectDataSource>
</EditItemTemplate>

L'interfaccia di modifica è disposta come l'interfaccia Read-Only

Figura 7: L'interfaccia di modifica è disposta come l'interfaccia Read-Only (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 3: Creazione dei gestori eventi EditCommand e CancelCommand

Attualmente non esiste alcuna sintassi di associazione dati in EditItemTemplate ( ad eccezione di UnitPriceLabel, che è stato copiato su verbatim da ItemTemplate). Si aggiungerà momentaneamente la sintassi di associazione dati, ma prima di tutto si creeranno i gestori eventi per gli eventi e CancelCommand di EditCommand DataList. Tenere presente che la responsabilità del gestore eventi consiste nel eseguire il rendering dell'interfaccia EditCommand di modifica per l'elemento DataList su cui è stato fatto clic sul pulsante Modifica, mentre il CancelCommand processo è quello di restituire DataList allo stato di pre-modifica.

Creare questi due gestori eventi e farli usare il codice seguente:

protected void Products_EditCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property and rebind the data
    Products.EditItemIndex = e.Item.ItemIndex;
    Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
    // Return to DataList to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

Con questi due gestori eventi sul posto, facendo clic sul pulsante Modifica viene visualizzata l'interfaccia di modifica e facendo clic sul pulsante Annulla viene restituito l'elemento modificato alla modalità di sola lettura. La figura 8 mostra DataList dopo che è stato fatto clic sul pulsante Modifica per Chef Anton s Gumbo Mix. Poiché è ancora stato aggiunto qualsiasi sintassi di associazione dati all'interfaccia di modifica, TextBox ProductName è vuoto, Discontinued checkBox deselezionato e i primi elementi selezionati da Categories e Suppliers DropDownLists.

Screenshot che mostra l'oggetto DataList EditItemTemplate dopo l'aggiunta dei gestori eventi EditCommand e CancelCommand e il pulsante Modifica è stato selezionato.

Figura 8: Facendo clic sul pulsante Modifica viene visualizzata l'interfaccia di modifica (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 4: Aggiunta della sintassi DataBinding all'interfaccia di modifica

Per fare in modo che l'interfaccia di modifica visualizzi i valori del prodotto corrente, è necessario usare la sintassi databinding per assegnare i valori dei campi dati ai valori appropriati del controllo Web. La sintassi di associazione dati può essere applicata tramite il Designer passando alla schermata Modifica modelli e selezionando il collegamento Modifica dataBindings dagli smart tag dei controlli Web. In alternativa, la sintassi di associazione dati può essere aggiunta direttamente al markup dichiarativo.

Assegnare il valore del ProductName campo dati alla ProductName proprietà TextBox s Text , i valori dei CategoryID campi dati e SupplierID alle Categories proprietà e Suppliers DropDownLists SelectedValue e il valore del Discontinued campo dati alla Discontinued proprietà CheckBox s Checked . Dopo aver apportato queste modifiche, tramite il Designer o direttamente tramite il markup dichiarativo, rivedere la pagina tramite un browser e fare clic sul pulsante Modifica per Chef Anton s Gumbo Mix. Come illustrato nella figura 9, la sintassi databinding ha aggiunto i valori correnti in TextBox, DropDownLists e CheckBox.

Screenshot che mostra l'oggetto DataList EditItemTemplate dopo l'aggiunta della sintassi DataBinding e dopo l'opzione Modifica selezionata.

Figura 9: Facendo clic sul pulsante Modifica viene visualizzata l'interfaccia di modifica (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 5: Salvataggio delle modifiche dell'utente nel gestore eventi UpdateCommand

Quando l'utente modifica un prodotto e fa clic sul pulsante Aggiorna, si verifica un postback e viene generato l'evento di UpdateCommand DataList. Nel gestore eventi è necessario leggere i valori dai controlli Web nell'interfaccia EditItemTemplate e con il BLL per aggiornare il prodotto nel database. Come illustrato nelle esercitazioni precedenti, l'oggetto ProductID del prodotto aggiornato è accessibile tramite la DataKeys raccolta. I campi immessi dall'utente sono accessibili facendo riferimento a livello di codice ai controlli Web tramite FindControl("controlID"), come illustrato nel codice seguente:

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
    // Make sure the page is valid...
    if (!Page.IsValid)
        return;
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
    // Read in the product name and price values
    TextBox productName = (TextBox)e.Item.FindControl("ProductName");
    DropDownList categories = (DropDownList)e.Item.FindControl("Categories");
    DropDownList suppliers = (DropDownList)e.Item.FindControl("Suppliers");
    CheckBox discontinued = (CheckBox)e.Item.FindControl("Discontinued");
    string productNameValue = null;
    if (productName.Text.Trim().Length > 0)
        productNameValue = productName.Text.Trim();
    int categoryIDValue = Convert.ToInt32(categories.SelectedValue);
    int supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);
    bool discontinuedValue = discontinued.Checked;
    // Call the ProductsBLL's UpdateProduct method...
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue,
                              discontinuedValue, productID);
    // Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

Il codice inizia consultando la Page.IsValid proprietà per assicurarsi che tutti i controlli di convalida nella pagina siano validi. Se Page.IsValid è True, il valore del ProductID prodotto modificato viene letto dalla DataKeys raccolta e viene fatto riferimento ai controlli Web di immissione dei dati in EditItemTemplate . Successivamente, i valori di questi controlli Web vengono letti in variabili che vengono quindi passate all'overload appropriato UpdateProduct . Dopo l'aggiornamento dei dati, DataList viene restituito allo stato di pre-modifica.

Nota

È stata omessa la logica di gestione delle eccezioni aggiunta nell'esercitazione Sulla gestione di BLL- e DAL-Level eccezioni per mantenere attivo il codice e questo esempio. Come esercizio, aggiungere questa funzionalità dopo aver completato questa esercitazione.

Passaggio 6: Gestione dei valori CategoryID NULL e SupplierID

Il database Northwind consente NULL i valori per le colonne e SupplierID della Products tabellaCategoryID. Tuttavia, l'interfaccia di modifica attualmente non supporta NULL i valori. Se si tenta di modificare un prodotto con un NULL valore per le colonne CategoryID o , SupplierID verrà visualizzato un ArgumentOutOfRangeException messaggio di errore simile al seguente: 'Categories' ha un selectedValue non valido perché non esiste nell'elenco di elementi. Inoltre, attualmente non è possibile modificare la categoria o il valore del fornitore di un prodotto da un valore diversoNULL a uno NULL .

Per supportare NULL i valori per la categoria e i fornitori DropDownLists, è necessario aggiungere un altro ListItemoggetto . Ho scelto di usare (Nessuno) come Text valore per questo ListItem, ma è possibile modificarlo in un altro (ad esempio una stringa vuota) se si desidera. Infine, ricordarsi di impostare DropDownLists AppendDataBoundItems su True. Se si dimentica di farlo, le categorie e i fornitori associati a DropDownList sovrascriveranno l'oggetto aggiunto ListItemin modo statico.

Dopo aver apportato queste modifiche, il markup DropDownLists in DataList s EditItemTemplate dovrebbe essere simile al seguente:

<asp:DropDownList ID="Categories" DataSourceID="CategoriesDataSource"
    DataTextField="CategoryName" DataValueField="CategoryID" runat="server"
    SelectedValue='<%# Eval("CategoryID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
...
<asp:DropDownList ID="Suppliers" DataSourceID="SuppliersDataSource"
    DataTextField="CompanyName" DataValueField="SupplierID" runat="server"
    SelectedValue='<%# Eval("SupplierID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>

Nota

Gli elementi statici ListItem possono essere aggiunti a un oggetto DropDownList tramite il Designer o direttamente tramite la sintassi dichiarativa. Quando si aggiunge un elemento DropDownList per rappresentare un valore di database NULL , assicurarsi di aggiungere tramite ListItem la sintassi dichiarativa. Se si usa il ListItem Editor Collection nel Designer, la sintassi dichiarativa generata ometterà completamente l'impostazione Value quando viene assegnata una stringa vuota, creando markup dichiarativo come: <asp:ListItem>(None)</asp:ListItem>. Sebbene ciò possa sembrare innocuo, l'elemento mancante Value fa sì che DropDownList usi il valore della Text proprietà al suo posto. Ciò significa che se NULLListItem questa opzione è selezionata, il valore (Nessuno) verrà tentato di essere assegnato al campo dati del prodotto (CategoryID o SupplierID, in questa esercitazione), che genererà un'eccezione. Impostando Value=""in modo esplicito , un NULL valore verrà assegnato al campo dati del prodotto quando NULLListItem viene selezionato .

Dedicare qualche minuto a visualizzare lo stato di avanzamento tramite un browser. Quando si modifica un prodotto, si noti che e CategoriesSuppliers DropDownLists hanno entrambe un'opzione (Nessuno) all'inizio dell'elenco a discesa.

Gli elenchi a discesa Categorie e Fornitori includono un'opzione (nessuna)

Figura 10: Gli Categories elenchi a discesa e Suppliers includono un'opzione (Nessuna) (Fare clic per visualizzare l'immagine a dimensione intera)

Per salvare l'opzione (Nessuno) come valore del database NULL , è necessario tornare al UpdateCommand gestore eventi. Modificare le categoryIDValue variabili e supplierIDValue in modo che siano numeri interi nullable e assegnarle un valore diverso Nothing da solo se dropDownList s SelectedValue non è una stringa vuota:

int? categoryIDValue = null;
if (!string.IsNullOrEmpty(categories.SelectedValue))
    categoryIDValue = Convert.ToInt32(categories.SelectedValue);
int? supplierIDValue = null;
if (!string.IsNullOrEmpty(suppliers.SelectedValue))
    supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);

Con questa modifica, un valore di Nothing verrà passato al UpdateProduct metodo BLL se l'utente ha selezionato l'opzione (Nessuno) da uno degli elenchi a discesa, che corrisponde a un NULL valore del database.

Riepilogo

In questa esercitazione è stato illustrato come creare un'interfaccia di modifica DataList più complessa che include tre diversi controlli Web di input, un controllo TextBox, due DropDownList e un controllo CheckBox insieme ai controlli di convalida. Quando si compila l'interfaccia di modifica, i passaggi sono gli stessi indipendentemente dai controlli Web usati: iniziare aggiungendo i controlli Web a DataList s EditItemTemplate. Utilizzare la sintassi databinding per assegnare i valori dei campi dati corrispondenti con le proprietà del controllo Web appropriate; e, nel UpdateCommand gestore eventi, accedere a livello di codice ai controlli Web e alle relative proprietà appropriate, passando i valori nel BLL.

Quando si crea un'interfaccia di modifica, indipendentemente dal fatto che sia composta solo da TextBoxes o da una raccolta di controlli Web diversi, assicurarsi di gestire correttamente i valori del database NULL . Quando si considera NULL s, è fondamentale non solo visualizzare correttamente un valore esistente NULL nell'interfaccia di modifica, ma anche che si offre un mezzo per contrassegnare un valore come NULL. Per DropDownLists in DataLists, in genere significa aggiungere una proprietà statica ListItem la cui Value proprietà è impostata in modo esplicito su una stringa vuota (Value="") e aggiungere un bit di codice al UpdateCommand gestore eventi per determinare se è NULL``ListItem stato selezionato o meno .

Buon programmatori!

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, lavora con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto all'indirizzo mitchell@4GuysFromRolla.com. o tramite il suo blog, disponibile all'indirizzo http://ScottOnWriting.NET.

Grazie speciale a

Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali di questa esercitazione sono stati Dennis Patterson, David Suru e Randy Schmidt. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.