La GridView gestisce la visualizzazione dei dati tramite diversi tipi di colonne, tra cui il default è il tipo BoundField.
Il BoundField permette di definire il nome dell'elemento della sorgente dati che si vuole visualizzare.
Nel caso lavorassimo con un Domain Model nel BoundField definiremo nell'attributo DataField il nome della proprietà dell'entità che si sta "legando" alla griglia.
Per esempio, se vado in DataBind con una Collection<Products>, potrò visualizzare il nome usando in DataField il valore Products.Name.
Il problema è che invece non permette di associare il valore di una proprietà complessa.
Per esempio la mia entità Products potrebbe avere una proprietà Category che a sua volta ha una proprietà Code.
Se la query che ritorna Collection<Products> valorizza correttamente sia Products che Category, quello che voglio è poter inserire nella griglia un campo BoundField che punti a Products.Category.Code.
Verificando con Reflector il funzionamento del BoundField si può notare come sia radicalmente cambiato il sistema di DataBinding rispetto alla DataGrid nella versione 1.1.
Per ovviare al problema ho realizzato una classe SmartBoundField da utilizzarsi al posto dell'originale BoundField in modo da poter supportare il Complex Property Binding.
La soluzione è molto semplice e consiste nel ritornare all'utilizzo di DataBinder.Eval il quale valuta correttamente le espressioni anche complesse.
protected override void OnDataBindField(object sender, EventArgs e)
{
// Complex property binding is not supported by BoundField
// so we have to put a litte trick to do that.
if (this.DataField.Contains("."))
{
this.ComplexPropertyBindingOnDataBindField(sender, e);
}
else
{
base.OnDataBindField(sender, e);
}
}
private void ComplexPropertyBindingOnDataBindField(object sender, EventArgs e)
{
object value = DataBinder.Eval(((GridViewRow)((Control)sender).Parent).DataItem, this.DataField);
bool encode = (this.SupportsHtmlEncode && this.HtmlEncode) && (sender is TableCell);
string text = this.FormatDataValue(value, encode);
if (sender is TableCell)
{
if (text.Length == 0)
{
text = " ";
}
((TableCell)sender).Text = text;
}
else
{
if (this.ApplyFormatInEditMode)
{
((TextBox)sender).Text = text;
}
} }