Sviluppo di controlli server Web personalizzati con associazione a dati per ASP.NET 2.0

Aggiornamento: novembre 2007

I controlli server Web ASP.NET con associazione a dati offrono un'interfaccia utente per un'origine dati che rappresenta un insieme di record o elementi. I controlli server Cenni preliminari sul controllo server Web GridView, Cenni preliminari sul controllo server Web DataList e Cenni preliminari sul controllo server Web Repeater sono esempi di controlli server Web con associazione a dati. Per ulteriori informazioni sui controlli con associazione a dati forniti con ASP.NET, vedere Cenni preliminari sui controlli server Web ASP.NET con associazione a dati.

Grazie al nuovo modello di origine dati disponibile in ASP.NET versione 2.0 è possibile associare controlli con associazione a dati a controlli del codice sorgente, eliminando così dal controllo con associazione a dati operazioni comuni relative ai dati, quali il paging, l'ordinamento e l'eliminazione. Questo modello garantisce un controllo con associazione a dati più flessibile per gli sviluppatori della pagina e aumenta il livello di riutilizzo.

In questo argomento vengono introdotti i passaggi di base necessari per implementare un controllo server personalizzato ASP.NET 2.0 con associazione a dati. Per ulteriori informazioni sull'architettura generale e le implementazioni dei controlli personalizzati, vedere Sviluppo di controlli server ASP.NET personalizzati e Procedura dettagliata: sviluppo e utilizzo di un controllo server personalizzato. Per ulteriori informazioni sullo sviluppo di controlli con associazione a dati compatibili con ASP.NET 1.1, vedere Sviluppo di controlli server Web personalizzati con associazione a dati per ASP.NET 1.1 e Procedura dettagliata: creazione di un controllo Web ASP.NET personalizzato con associazione a dati per ASP.NET 1.1. Per ulteriori informazioni sui controlli origine dati, vedere Cenni preliminari sui controlli origine dati.

Quando creare un controllo personalizzato con associazione a dati

Prima di creare un controllo personalizzato con associazione a dati, rivedere le funzionalità dei controlli con associazione a dati fornite con ASP.NET. I controlli esistenti potrebbero soddisfare le esigenze specifiche del caso oppure si può decidere di creare un controllo personalizzato che estende un controllo esistente che fornisce già molte delle funzionalità necessarie. Per ulteriori informazioni sui controlli con associazione a dati forniti con ASP.NET, vedere Cenni preliminari sui controlli server Web ASP.NET con associazione a dati.

Di seguito sono riportate alcune ragioni che possono far propendere per la creazione di un controllo personalizzato con associazione a dati:

  • Per le esigenze specifiche del caso sono necessarie un'interfaccia utente personalizzata, funzionalità personalizzate di ordinamento dei dati e funzionalità personalizzate di modifica dei dati che non sono disponibili nei controlli con associazione a dati esistenti.

  • Si desidera creare un controllo personalizzato con associazione a dati precompilato e ridistribuibile.

  • Si desidera estendere le funzionalità di un controllo con associazione a dati fornito con ASP.NET.

  • Si desidera creare un controllo con associazione a dati con una finestra di progettazione personalizzata adattata alle necessità specifiche del caso.

Funzionalità di base di un controllo personalizzato con associazione a dati

Derivando da una delle classi base del controllo con associazione a dati, ad esempio la classe DataBoundControl o CompositeDataBoundControl, il controllo personalizzato con associazione a dati eredita automaticamente numerose funzionalità incorporate, incluse le seguenti:

  • Supporto dell'origine dati per l'interfaccia IDataSource e la classe DataSourceView correlata che fornisce visualizzazioni denominate dei dati, la possibilità di eseguire query per i tipi di operazioni supportate dall'archivio dati e la funzionalità di caricamento dati su richiesta.

  • Supporto dell'origine dati per le interfacce generiche IEnumerable e IListSource.

  • Supporto per le espressioni di associazione a dati che consentono agli sviluppatori della pagina di creare associazioni tra una proprietà esposta e contrassegnata in modo speciale del controllo e un'origine dati. Per ulteriori informazioni sulle espressioni di associazione dati, vedere Cenni preliminari sulle espressioni di associazione dati.

  • Supporto per l'associazione dati automatica che richiama la logica di associazione a dati il più tardi possibile durante il ciclo di vita della pagina e solo quando necessario, invece che in occasione di ogni postback. Dopo che una pagina esegue la prima richiesta di associazione a dati, le richieste successive tentano di recuperare i dati dallo stato di visualizzazione. In questo modo le prestazione risultano migliorate in quanto si elimina la necessità di riconnettersi all'origine dati a ogni richiesta.

Utilizzo delle funzionalità della fase di progettazione disponibili

Ci sono funzionalità della fase di progettazione disponibili per tutti i controlli server Web che è possibile prendere in considerazione per il controllo personalizzato con associazione a dati. È possibile creare una classe della finestra di progettazione e modelli per il controllo personalizzato. Queste funzionalità vengono richiamate quando il controllo viene utilizzato in fase di progettazione su un'area di progettazione visiva, ad esempio nella visualizzazione Progettazione di Visual Studio.

La creazione di una finestra di progettazione per il controllo aumenta considerevolmente le possibilità di utilizzo del controllo personalizzato in fase di progettazione. L'interfaccia utente della fase di progettazione semplifica infatti la personalizzazione delle proprietà del controllo. Per una panoramica sulle finestre di progettazione dei controlli ASP.NET, vedere Cenni preliminari sulle finestre Progettazione controlli ASP.NET. Per i relativi esempi, vedere HierarchicalDataBoundControlDesigner e Procedura dettagliata: creazione di una finestra Progettazione controlli di base per un controllo server Web.

Creando un controllo basato su modelli, si offre allo sviluppatore della pagina la flessibilità necessaria per specificare i controlli e i tag che definiscono l'interfaccia utente del controllo. Per un esempio di un controllo personalizzato basato su modelli, vedere Esempio di controllo server basato su modelli.

Implementazione di un controllo personalizzato con associazione a dati in ASP.NET 2.0

Nella tabella riportata di seguito è incluso un riepilogo dei passaggi specifici all'implementazione di un controllo server personalizzato con associazione a dati in ASP.NET 2.0. Dopo la tabella, vengono fornite informazioni dettagliate su ogni passaggio dell'implementazione.

Passaggio

Riepilogo del passaggio

Scegliere una classe base del controllo con associazione a dati.

Estendere una classe del controllo con associazione a dati esistente che fornisce già numerose delle funzionalità necessarie o derivare da una delle classi base del controllo con associazione a dati.

Esporre le proprietà dell'associazione a dati.

Configurare il controllo personalizzato per esporre le proprietà dell'associazione a dati che si vanno ad aggiungere alle proprietà minime richieste per l'associazione a dati esposte dalle classi base del controllo con associazione a dati.

Avviare il recupero dei dati.

  • Recuperare i dati che lo sviluppatore della pagina ha assegnato al controllo eseguendo le operazioni seguenti:

  • Un override del metodo PerformSelect della classe base del controllo con associazione a dati.

  • Una chiamata al metodo GetData della classe base del controllo con associazione a dati per recuperare la visualizzazione dell'origine dati del controllo.

  • Una chiamata al metodo Select dell'oggetto DataSourceView per avviare il recupero dei dati e specificare il metodo di callback che riceverà i dati.

Gestire i dati recuperati.

Fornire il metodo di callback specificato come parametro nel metodo Select. Questo metodo deve avere un singolo parametro del tipo IEnumerable per ricevere i dati. Se il controllo richiede l'elaborazione dei dati, questa deve avvenire all'interno del metodo di callback.

Creare gli oggetti dell'interfaccia utente che rappresentano i dati.

Fornire un override del metodo PerformDataBinding. È necessario eseguire le attività seguenti all'interno di questo metodo:

  • Chiamare il metodo PerformDataBinding per consentire l'esecuzione di eventuale codice che si basa su questo metodo.

  • Enumerare tramite la raccolta di dati e creare i controlli figlio che rappresenteranno i dati nella visualizzazione dell'interfaccia utente.

Scelta di una classe base del controllo con associazione a dati

Gli sviluppatori di controlli possono estendere una delle classi base del controllo con associazione a dati disponibili per creare un controllo personalizzato con associazione a dati. Nella tabella riportata di seguito sono elencate le classi base con associazione a dati disponibili in ASP.NET 2.0. Rivedere le descrizioni di ogni classe e quindi determinare quale classe base meglio si adatta ai requisiti del controllo personalizzato con associazione a dati. Per informazioni dettagliate su ogni classe base per i controlli con associazione a dati e sugli esempi di implementazione, vedere la documentazione di riferimento relativa a ogni classe. Per ulteriori informazioni sui controlli con associazione a dati forniti con ASP.NET, vedere Cenni preliminari sui controlli server Web ASP.NET con associazione a dati.

Classe

Descrizione

BaseDataBoundControl

  • Si tratta della classe base per tutti i controlli con associazione a dati che esegue l'associazione dati e la convalida dei dati associati.

DataBoundControl

Si tratta della classe base con associazione a dati per la generazione di controlli con associazione a dati standard. La classe DataBoundControl esegue le operazioni seguenti:

  • Fornisce l'implementazione di base condivisa da tutti i controlli con associazione a dati.

  • Contiene la logica per comunicare con i controlli origine dati e i contenitori di dati.

  • Funge da base per i controlli con associazione a dati, ad esempio TreeView e ListControl.

ListControl

  • Si tratta della classe base per i controlli elenco ed estende la classe DataBoundControl. Fornisce un insieme Items e funzionalità avanzate per il rendering del layout.

CompositeDataBoundControl

  • Si tratta della classe base che estende la classe DataBoundControl, fornendo le funzionalità seguenti:

  • Implementa il codice tipico necessario per controlli compositi, incluso il codice che ripristina la gerarchia dei controlli figlio del controllo dallo stato di visualizzazione dopo l'esecuzione di un postback.

  • Associa a un'origine dati IEnumerable ed enumera i dati per generare una struttura di controlli.

  • Funge da base per i controlli con associazione a dati, ad esempio GridView e DetailsView.

HierarchicalDataBoundControl

  • Si tratta della classe base per i controlli che visualizzano i dati in modo gerarchico. Funge da base per i controlli con associazione a dati basati su struttura, ad esempio TreeView e Menu.

Proprietà di associazione dati fornite

Le classi base del controllo con associazione a dati forniscono le proprietà di associazione a dati esposte necessarie per consentire allo sviluppatore della pagina di associare un'origine dati a un controllo. Non è necessario alcun lavoro aggiuntivo da parte dell'autore del controllo. Derivando dalla classe DataBoundControl, un controllo personalizzato eredita ad esempio tre proprietà di associazione a dati esposte: DataSourceID, DataSource e DataMember. Lo sviluppatore della pagina può quindi specificare l'origine dei dati alla quale si assocerà il controllo impostando il valore della proprietà DataSource o DataSourceID.

La proprietà DataSourceID consente allo sviluppatore della pagina di specificare l'ID di un controllo che rappresenta l'origine dati dalla quale il controllo con associazione a dati recupera i dati.

La proprietà DataSource consente allo sviluppatore della pagina di associare un controllo con associazione a dati direttamente a oggetti dati dei due tipi seguenti:

  • Un oggetto che implementa l'interfaccia IEnumerable, ad esempio un oggetto Array, ArrayList o Hashtable.

  • Un oggetto che implementa l'interfaccia IListSource, ad esempio un oggetto DataSet.

  • Proprietà di associazione a dati aggiuntive, ad esempio la proprietà DataMember, consentono allo sviluppatore della pagina di specificare la porzione della raccolta di dati a cui deve essere associato il controllo.

  • Per ulteriori informazioni sulle proprietà di associazione a dati esposte fornite da ogni classe del controllo con associazione a dati o da ogni classe base con associazione a dati, vedere la documentazione di riferimento relativa a ogni classe.

Esposizione delle proprietà di associazione a dati personalizzate

Quando si espongono proprietà di associazione a dati personalizzate o si esegue l'override di proprietà con associazione a dati esistenti, è necessario chiamare il metodo OnDataPropertyChanged se il controllo è già stato inizializzato. In questo modo il controllo con associazione a dati deve associare nuovamente i dati per poter utilizzare l'impostazione della nuova proprietà con associazione a dati.

Nell'esempio di codice seguente è illustrata una proprietà che appartiene a una classe del controllo con associazione a dati derivata. L'esempio illustra come un controllo con associazione a dati possa chiamare il metodo OnDataPropertyChanged se una proprietà che identifica un'origine dati viene modificata dopo l'inizializzazione del controllo con associazione a dati.

Inherits DataBoundControl

Public Property DataTextField() As String
    Get
        Dim o As Object = ViewState("DataTextField")
        If o Is Nothing Then
            Return String.Empty
        Else
            Return CStr(o)
        End If
    End Get
    Set(ByVal value As String)
        ViewState("DataTextField") = value
        If (Initialized) Then
            OnDataPropertyChanged()
        End If
    End Set
End Property
public class SimpleDataBoundColumn : DataBoundControl
{
    public string DataTextField
    {
        get
        {
            object o = ViewState["DataTextField"];
            return ((o == null) ? string.Empty : (string)o);
        }
        set
        {
            ViewState["DataTextField"] = value;
            if (Initialized)
            {
                OnDataPropertyChanged();
            }
        }
    }

Avvio del recupero dei dati

Il recupero dei dati viene avviato all'interno di un override del metodo PerformSelect ereditato dal controllo base con associazione a dati del controllo. All'interno di questo override viene eseguita una chiamata per recuperare i dati e specificare un metodo di callback che gestirà i dati restituiti.

Per recuperare i dati, eseguire le attività seguenti nel metodo PerformSelect sottoposto a override:

  1. Determinare se lo sviluppatore della pagina ha utilizzato la proprietà DataSource o DataSourceID per impostare i dati da associare al controllo. Questa operazione viene eseguita verificando la proprietà IsBoundUsingDataSourceID. Ad esempio, un'impostazione false per la proprietà IsBoundUsingDataSourceID indica che la proprietà DataSource è stata utilizzata per specificare l'origine dati.

  2. Se lo sviluppatore della pagina ha impostato la proprietà DataSource, sarà necessario eseguire un passaggio aggiuntivo, ovvero chiamare il metodo OnDataBinding.

  3. Chiamare il metodo GetData per recuperare l'oggetto DataSourceView associato al controllo con associazione a dati.

  4. Chiamare il metodo Select dell'oggetto DataSourceView recuperato per avviare il recupero dei dati e specificare il metodo di callback che gestirà i dati recuperati. Poiché il metodo Select funziona in modo asincrono, è possibile sottoporre a elaborazione i dati in fase di recupero.

  5. Indicare il completamento delle attività PerformSelect impostando la proprietà RequiresDataBinding su false e chiamando quindi il metodo MarkAsDataBound.

  6. Generare l'evento OnDataBound.

Nell'esempio di codice seguente vengono illustrate le attività di recupero dei dati precedenti completate all'interno di un override del metodo PerformSelect.

Protected Overrides Sub PerformSelect()
    ' Call OnDataBinding here if bound to a data source using the
    ' DataSource property (instead of a DataSourceID), because the
    ' databinding statement is evaluated before the call to GetData.       
    If Not IsBoundUsingDataSourceID Then
        OnDataBinding(EventArgs.Empty)
    End If

    ' The GetData method retrieves the DataSourceView object from  
    ' the IDataSource associated with the data-bound control.            
    GetData().Select(CreateDataSourceSelectArguments(), _
        AddressOf OnDataSourceViewSelectCallback)

    ' The PerformDataBinding method has completed.
    RequiresDataBinding = False
    MarkAsDataBound()

    ' Raise the DataBound event.
    OnDataBound(EventArgs.Empty)

End Sub
protected override void PerformSelect()
{
    // Call OnDataBinding here if bound to a data source using the
    // DataSource property (instead of a DataSourceID), because the
    // databinding statement is evaluated before the call to GetData.       
    if (!IsBoundUsingDataSourceID)
    {
        this.OnDataBinding(EventArgs.Empty);
    }

    // The GetData method retrieves the DataSourceView object from  
    // the IDataSource associated with the data-bound control.            
    GetData().Select(CreateDataSourceSelectArguments(),
        this.OnDataSourceViewSelectCallback);

    // The PerformDataBinding method has completed.
    RequiresDataBinding = false;
    MarkAsDataBound();

    // Raise the DataBound event.
    OnDataBound(EventArgs.Empty);
}

Gestione dei dati recuperati

Creare metodo di callback personalizzato per accettare i dati recuperati. Si tratta del metodo di callback specificato quando è stato chiamato il metodo Select all'interno dell'override del metodo PerformSelect. Il metodo di callback è necessario per contenere un solo parametro del tipo IEnumerable. Nel metodo di callback è possibile eseguire l'elaborazione dei dati restituiti, se è richiesto dal controllo. Come ultimo passaggio, chiamare il metodo PerformDataBinding.

Nell'esempio di codice seguente viene illustrato un metodo di callback che ha un parametro di tipo IEnumerable e chiama il metodo PerformDataBinding.

Private Sub OnDataSourceViewSelectCallback(ByVal retrievedData As IEnumerable)
    ' Call OnDataBinding only if it has not already been 
    ' called in the PerformSelect method.
    If IsBoundUsingDataSourceID Then
        OnDataBinding(EventArgs.Empty)
    End If
    ' The PerformDataBinding method binds the data in the  
    ' retrievedData collection to elements of the data-bound control.
    PerformDataBinding(retrievedData)

End Sub
private void OnDataSourceViewSelectCallback(IEnumerable retrievedData)
{
    // Call OnDataBinding only if it has not already been 
    // called in the PerformSelect method.
    if (IsBoundUsingDataSourceID)
    {
        OnDataBinding(EventArgs.Empty);
    }
    // The PerformDataBinding method binds the data in the  
    // retrievedData collection to elements of the data-bound control.
    PerformDataBinding(retrievedData);
}

Creazione degli oggetti dell'interfaccia utente che rappresentano i dati

All'interno di un override del metodo PerformDataBinding vengono creati i controlli figlio che rappresenteranno i dati. La raccolta dei dati è enumerata, i controlli figlio vengono creati e le proprietà corrispondenti vengono impostate in base a ogni elemento dati. Aggiungendo i nuovi controlli figlio all'insieme Controls del controllo, verrà eseguito automaticamente il rendering di tali controlli. Il rendering della gerarchia del controllo viene eseguita durante il metodo Render ereditato del controllo. È possibile scegliere di eseguire l'override del metodo Render per eseguire un rendering speciale richiesto dal controllo personalizzato, ad esempio includendo elementi HTML aggiuntivi o rendering speciale per la visualizzazione in modalità di progettazione.

Per creare gli oggetti dell'interfaccia utente che rappresentano i dati, eseguire l'override del metodo PerformDataBinding ed eseguire le attività seguenti:

  1. Chiamare il metodo PerformDataBinding per consentire l'esecuzione di eventuale codice che si basa su questo metodo.

  2. Enumerare tramite la raccolta di dati e creare i controlli figlio che rappresenteranno i dati nella visualizzazione dell'interfaccia utente. Aggiungere ogni controllo figlio all'insieme del controllo chiamando il metodo Add del controllo.

  • Nell'esempio di codice riportato di seguito viene illustrato l'override del metodo PerformDataBinding. Il metodo PerformDataBinding viene chiamato per consentire l'esecuzione di eventuale codice che si basa su questo metodo. La raccolta dei dati è enumerata e i controlli figlio vengono creati per rappresentare i dati nella visualizzazione dell'interfaccia utente.
        Protected Overrides Sub PerformDataBinding(ByVal retrievedData As IEnumerable)
            MyBase.PerformDataBinding(retrievedData)

            ' Verify data exists.
            If Not (retrievedData Is Nothing) Then
                Dim tbl As New Table()
                Dim row As TableRow
                Dim cell As TableCell
                Dim dataStr As String = String.Empty

                Dim dataItem As Object
                For Each dataItem In retrievedData
                    ' If the DataTextField was specified get the data
                    ' from that field, otherwise get the data from the first field. 
                    If DataTextField.Length > 0 Then
                        dataStr = DataBinder.GetPropertyValue(dataItem, DataTextField, Nothing)
                    Else
                        Dim props As PropertyDescriptorCollection = TypeDescriptor.GetProperties(dataItem)
                        If props.Count >= 1 Then
                            If Nothing <> props(0).GetValue(dataItem) Then
                                dataStr = props(0).GetValue(dataItem).ToString()
                            End If
                        End If
                    End If

                    row = New TableRow()
                    tbl.Rows.Add(row)
                    cell = New TableCell()
                    cell.Text = dataStr
                    row.Cells.Add(cell)
                Next dataItem

                Controls.Add(tbl)
            End If

        End Sub
    End Class
End Namespace
protected override void PerformDataBinding(IEnumerable retrievedData)
{
    base.PerformDataBinding(retrievedData);

    // Verify data exists.
    if (retrievedData != null)
    {
        Table tbl = new Table();
        TableRow row;
        TableCell cell;
        string dataStr = String.Empty;

        foreach (object dataItem in retrievedData)
        {
            // If the DataTextField was specified get the data
            // from that field, otherwise get the data from the first field. 
            if (DataTextField.Length > 0)
            {
                dataStr = DataBinder.GetPropertyValue(dataItem,
                    DataTextField, null);
            }
            else
            {
                PropertyDescriptorCollection props =
                        TypeDescriptor.GetProperties(dataItem);
                if (props.Count >= 1)
                {
                    if (null != props[0].GetValue(dataItem))
                    {
                        dataStr = props[0].GetValue(dataItem).ToString();
                    }
                }
            }

            row = new TableRow();
            tbl.Rows.Add(row);
            cell = new TableCell();
            cell.Text = dataStr;
            row.Cells.Add(cell);
        }

        this.Controls.Add(tbl); 
    }
}

Generazione del controllo server personalizzato

Per informazioni sulla generazione del controllo server Web personalizzato con associazione a dati e sull'utilizzo di tale controllo in una pagina Web, vedere Generazione degli esempi dei controlli server personalizzati.

Vedere anche

Attività

Procedura dettagliata: creazione di un controllo Web ASP.NET personalizzato con associazione a dati per ASP.NET 2.0

Procedura dettagliata: sviluppo e utilizzo di un controllo server personalizzato

Concetti

Cenni preliminari sui controlli server Web ASP.NET con associazione a dati

Attributi di metadati per controlli server personalizzati

Cenni preliminari sulle finestre Progettazione controlli ASP.NET

Riferimenti

HierarchicalDataBoundControlDesigner

Altre risorse

Sviluppo di controlli server ASP.NET personalizzati