ASP.NET ha una nutrita serie di controlli studiati per le più disparate esigenze di visualizzazione dati, ciò nonostante è del tutto assente un campo per la visualizzazione di una DropDownList in un Data Control, come GridView o DetailsView.
Benché il problema sia facilmente risolvibile utilizzando la malleabile TemplateField, alla lunga tale soluzione è scomoda specialmente se costretti a ripetere il medesimo markup in più pagine.
Per evitare di cadere in errori causati da copia/incolla, la soluzione migliore consiste nel realizzare un field come custom contro.
Il primo passo è decidere la classe da derivare, nel nostro caso la scelta più adatta è la classe BoundField perché dispone già di un metodo per formattare i dati, FormatDataValue, ed uno per recuperare dalla fonte dati il campo da visualizzare, GetValue.
I metodi di cui è indispensabile eseguire l'override sono tre: InizializzeDataCell, ExtractValuesFromCell e OnDataBindField.
InizializzeDataCell viene eseguito ogniqualvolta è necessario aggiungere a una cella il controllo o i controlli necessari a visualizzare i dati provenienti dalla fonte dati e non viene richiamato per creare l'header o il footer.
Per realizzare la nostra field custom è necessario aggiungere alla cella una DropDownList, qualora si trovi in modalità di Edit o Insert, e registrare per l'evento DataBound un event handler che punti al metodo OnDataBindField. Infine per recuperare la selezione dell'utente basta sfruttare l'override del metodo ExtractValuesFromCell.
protected override void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
{
// controllo se devo aggiungere la DropDownList
if (IsInputMode(rowState))
{
// la istanzio
DropDownList _dropDownList = new DropDownList();
// e imposto le proprietà necessarie
_dropDownList.DataTextField = DataTextField;
_dropDownList.DataValueField = DataValueField;
_dropDownList.AppendDataBoundItems = true;
//aggiungo un elemento neutro
_dropDownList.Items.Add(new ListItem(ItemTextEmptyValue, ItemValuetEmptyValue));
// aggiungo il controllo alla cella
cell.Controls.Add(_dropDownList);
//se sono in DesignMode
if (DesignMode)
{
if (!string.IsNullOrEmpty(DataSourceID))
_dropDownList.Items.Add("DataBound");
}
else
{
//imposto la sorgente dati
_dropDownList.DataSourceID = DataSourceID;
//per la modalità Insert non ho bisogno di gesire l'evento
if ((rowState & DataControlRowState.Insert) != DataControlRowState.Insert)
_dropDownList.DataBound += new EventHandler(OnDataBindField);
}
}
else
{
cell.DataBinding += new EventHandler(OnDataBindField);
}
}In seguito eseguiamo l'override del metodo OnDataBindField, eseguito come risposta all'evento DataBound della DropDownList (modalita di Edit e Insert) e per quello di DataBind della cella.
Nel caso non sia trovata corrispondenza tra il campo della fonte dati associata al GridView e i valori dell'item della DropDownList, questo viene memorizzato nel campo OccasionalField.
protected override void OnDataBindField(object sender, EventArgs e)
{
//casto l'oggetto che a gererato l'evento ad un generico riferimento a Control
Control _control = (Control)sender;
DropDownList _dropDownList = sender as DropDownList;
DataControlFieldCell _dataControlFieldCell = sender as DataControlFieldCell;
//controllo se è necessatio encodare i dati
bool encode = (SupportsHtmlEncode && HtmlEncode) && (sender is TableCell);
//estraggo il volore
_occasionalOldValue = this.GetValue(_control.NamingContainer);
//se il sender è una DropDownList
if (_dropDownList != null)
{
//recupero l'idice del item usando come chiave di ricerca il valore recuperato dallo sorgente dati
int _index = _dropDownList.Items.IndexOf(_dropDownList.Items.FindByValue(_occasionalOldValue.ToString()));
//se l'intem è presente nella fonte dati
if (_index > -1)
_occasionalOldValue = null;
//imposto l'indice selezionato
_dropDownList.SelectedIndex = _index;
}
//se il sender è una cella con dati
else if (_dataControlFieldCell != null)
{
if (this.DesignMode)
_dataControlFieldCell.Text = "abc";
else
//formatto il valore
_dataControlFieldCell.Text = FormatDataValue(_occasionalOldValue, encode);
}
}Infine non rimane che eseguire l'override del metodo ExtractValuesFromCell allo scopo di recuperare il valore selezionato dalla DropDownList:
public override void ExtractValuesFromCell(System.Collections.Specialized.IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
{
//se la DropDownList è stata aggiunta
if (cell.Controls.Count > 0)
{
//recupero il riferimento
DropDownList _dropDownList = cell.Controls[0] as DropDownList;
if (_dropDownList != null)
{
// recupero il valore (siaprecedente che attuale)
object _dataField = _occasionalOldValue == null ? _dropDownList.SelectedValue : _occasionalOldValue;
//l'aggiungo alla collezione dei parametri
if (dictionary.Contains(DataField))
{
dictionary[DataField] = _dataField;
}
else
{
dictionary.Add(DataField, _dataField);
}
}
}
else
{
base.ExtractValuesFromCell(dictionary, cell, rowState, includeReadOnly);
}
}- Galleria fotografica dinamica con ASP.NET AJAX
- #926 - Autenticazione con Membership API e selezione del dominio per Active Directory
- #920 - Utilizzare HttpModule in modalità asincrona
- #950 - Il supporto al pulsante back del browser con ASP.NET AJAX 3.5 SP 1
- Rilasciata la preview 1 di ASP.NET Ajax 4.0
- Speciale ASP.NET security
- #933 - Una GridView con supporto per più righe selezionabili
- Disponibile parte del codice sorgente del Framework
- Cosa c'è in ASP.NET 3.5 Service Pack1
- Realizzare un custom extender AJAX con ASP.NET 3.5
- #906 - Specificare la Culture della pagina con InitializeCulture
- I bug di ASP.NET AJAX 1.0 risolti con ASP.NET AJAX 3.5
Esprimi il tuo giudizio su questo script:
Per procedere devi essere autenticato.
Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.







Stampa
Snippet
Download 


10annidi.ASPItalia.com: iscriviti alla competizione e vinci fantastici premi ogni mese!