Il Binding è attivo al momento della popolazione
della Data Grid quando cioè il DataSource è stato assegnato alla DataGrid
ed è stato eseguito il Bind e cioè durante gli eventi di ItemCreated,
ItemDataBound e DataBinding . L'assegnazione del DataSource alla DataGrid
può essere ripetuta in più occasioni avendo cura di mantenere in memoria
ed inalterato il DataSource. L'accesso ai dati avviene con le medesime
tecniche usate per indicare esplicitamente una espressione di Binding personalizzato
quindi quanto detto in seguito vale anche per le espressioni di Binding.
Ecco due tecniche per accedere alla riga del DataSource corrisponde ad una
riga nella DataGrid :
- Con cast esplicito
((DataRowView)E.Item.DataItem)["OrderID"])
Ovviamente bisogna indicare il nome della colonna a cui accedere,
ma bisogna indicare anche il tipo della fonte dati (DataRowView nell'esempio)
che potrebbe variare a seconda si usi per DataSource un DataTable, una
DataView un DataReader o magari una Array o una collezione.
In questo caso E è l'argomento di un evento della griglia,
in alternativa ad E.Item posso indicare Datagrid1.Items[idx] :
((DataRowView)Datagrid1.Items[idx].DataItem)["OrderID"])
dove idx è l'indice della riga.
Qualora si voglia specificare una espressione personalizzata per popolare
un controllo in Binding (solitamente nella griglia per le <BoundColumn>
e le <TemplateColumn> ) l'espressione sarebbe:
<%# ((DataRowView)Container.DataItem)["OrderID"]%>
a cui si aggiunge solitamente lo String.Format per controllare la
visualizzazione testuale del dato in griglia .
- Con DataBinder
DataBinder.Eval(E.Item.DataItem, "OrderID")
Impiegando il DataBinder è possibile accedere al dato semplicemente
indicando il nome della colonna e quindi indipendentemente dal tipo della
fonte dati impiegata.
Qualora si voglia specificare una espressione personalizzata per popolare
un controllo in Binding (solitamente nella griglia per le <BoundColumn>
e le <TemplateColumn> ) l'espressione sarebbe:
<%# DataBinder.Eval(Container.DataItem, "OrderID",
"{0:c}") %>
in cui compare anche la formattazione della visualizzazione testuale
del dato in griglia.
Quale tecnica usare?
La documetazione MSDN a proposito del DataBinder dice:
CAUTION Since this method performs late-bound evaluation,
using reflection, at runtime, it can cause performance to noticeably slow
compared to standard ASP.NET data-binding syntax.
Segue domanda e risposta poste ad una mailing-list.
-----------------------------------------------------------------------------
Date: Mon, 10 Dec 2001 01:30:57 -0800
From: Luca Minudel
Subject: DataBinder.Eval and FindControl... should I use them?
I've seen that ASP.NET QuickStart examples use DataBinder.Eval for
automatic casting and formatting while binding
<%# DataBinder.Eval(Container.DataItem, "OrderID", "{0:c}") %>
I've tryed to do it myself without DataBinder.Eval
<%# String.Format("{0:c}", ((DataRowView)Container.DataItem)["OrderID"])%>
I do it just to learn how thinks work. But now I'd like to know if I should
continue to use DataBinder.Eval or I shouldn't... and why?
-----------------------------------------------------------------------------
Date: Tue, 11 Dec 2001 13:57:47 -0800
From: Conrad Chan
Using DataBinder.Eval hides the detail about the structure of the
underlying data source from the ASPX page. In your example of not using
DataBinder, you have to know your underlying datasource which is a
dataRowView. Using DataBinder.Eval approach simply gives you more room to
change in the future. To me, there is nothing wrong with either approach.
It is simply a design decision for you particular use cases.
Conrad
-----------------------------------------------------------------------------
Date: Wed, 12 Dec 2001 00:39:03 -0800
From: Luca Minudel
>In your example of not using DataBinder, you have to know your underlying
>datasource which is a dataRowView.
In my example the cast to the underlyng datasource is resolved at run-time
(just like with DataBinder.Eval I think).
How can I code the binding to allow this check at compile-time?
-----------------------------------------------------------------------------
Date: Wed, 12 Dec 2001 09:59:39 -0800
From: Conrad Chan
First of all, DataBinder uses reflection instead of casting to load
data. Both styles bind the data at run-time. The only difference is the
flexibility. Say if you need to switch to use other datasource type for
some reason like DataTable or an array of typed objects, your
DataBinder.Eval code will continue to work.
-----------------------------------------------------------------------------
QUANDO IL BINDING NON E' ATTIVO
Come prima cosa bisogna ricordare che
le informazioni visualizzate nella pagina corrente dalla DataGrid e raccolte
tramite DataSource sono memorizzate in forma testuale nello stato della
DataGrid (cioè nel ViewState) e successive visualizzazioni della medesima
pagina della DataGrid (a seguito di operazioni dell'utente che provocano
il submit della pagina, l'esecuzione dell'evento sul server e il successivo
invio della pagina modificata al client) si baseranno sulle informazioni
mantenute nello stato (il ViewState) e non su quelle del DataSource al
quale la DataGrid non ha più riferimenti.
E' possibile scoprire quale riga del DataSource corrisponde ad una
riga visualizzata nella DataGrid anche senza ripetere l'operazione di Binding
che è una operazione costosa in termini di tempo CPU (ricordo che la memorizzazione
del DataSource è comunque a carico del programmatore come descritto sopra
in
ADO.NET e pagine Web
).
Ecco come. Sia con una DataGrid che con una DataList si può impostare
il
DataKeyField per indicare quale campo del DataSource
è il campo chiave. Ciò causerà la popolazione della collezione DataKeys
del controllo. Una volta che la collezione è popolata risulta facile, dentro
un evento del controllo, ottenere il valore della chiave relativa alla riga
corrente con l'espressione
MiaDataTable.DataKeys[e.Item.ItemIndex] XXX
|
Il campo chiave così ottenuto può essere
usato per trovare la rispettiva riga del DataSource con cui è stata popolata
la griglia (come descritto in seguito in
Cercare, filtrare, ordinare
) o compiere altre elaborazioni.
Quando la chiave è composta da più colonne non è possibile usare
DataKeyField e DataKeys; ci sono due alternative: