Comment « Binder » les propriétés d’un Extender Atlas Control ToolKit
La question est la suivante :Comment, si je mets un Extender dans un template d’une grille, je vais pouvoir « Binder » une de ses propriétés sur une colonne de mes données.Pouvoir écrire ceci :
<asp:TemplateField HeaderText="Priority">
<EditItemTemplate>
<atlasToolkit:NumericUpDownExtender ID="NumericUpDownExtender2" runat="server">
<atlasToolkit:NumericUpDownProperties
ID="NumericUpDownProperties1"
TargetControlID="tbPriority"
Width="50"
Tag='<%# Bind("Priority") %>'
ServiceUpMethod="NextValue"
ServiceDownMethod="PrevValue" />
</atlasToolkit:NumericUpDownExtender>
<asp:TextBox ID="tbPriority" runat="server" Text='<%# Bind("Priority") %>'></asp:TextBox>
</EditItemTemplate>
..
</asp:TemplateField>
Avec ASP.NET v2 le Binding (association données / contrôles) parait magique mais en fait quand on regarde dans Reflector on remarque que les contrôles conteneurs de données tel que la GridView ou la FormView appelent dans leur méthode CreateChildControls() la méthode DadaBind() et DataBindChildren() (qui appel DadaBind() sur ses contrôles enfants). Donc on pourrait se dire que le Binding dans les « Extender » marche directement mais le problème avec les « Extender » c’est qu’ils utilisent des TargetControlProperties pour référencer les contrôles à étendre.
Ces derniers n’héritent pas de « Control » mais de « Object », le Binding n’est donc pas appelé automatiquement.
Tout d’abord pour qu’un composant soit Bindable il faut qu’il expose 2 choses :
public event EventHandler DataBinding [add/remove] – EventHandler à appeler au moment où on Bind
public Control BindingContainer[get] – Renvoyer le contrôle conteneur rattaché à la DataSource.
Une fois qu’on a rajouté ceci au « TargetControlProperties» l’écriture de Binding <%# Bind("Priority") %> est autorisé dans la page ASPX, mais le Binding de l’extendeur n’est pas lancé par le Binding en cascade du contrôle.
L’astuce est, de détourner l’appel de Binding du contrôle auquel l’Extender est rattaché (ici la TextBox), pour appeler le Binding du « TargetControlProperties » au même moment.
Donc dans la classe de l’ « Extender » (celui qui crée les « TargetControlProperties ») on va s’accrocher a l’événement de Binding du contrôle étendu.
protected
override void OnLoad(EventArgs e)
{
base.OnLoad(e);
for (int i =0; i < TargetProperties.Count; i++)
{
NumericUpDownProperties numericUpDownProperties = base.TargetProperties[ i ];
Control targetControl = GetTargetControl(numericUpDownProperties);
targetControl.DataBinding += new EventHandler(numericUpDownProperties.DataBind);
}
}
Ainsi quand le DataBinding sur le targetControl sera appelé, le targetControl appellera la méthode de DataBinding de son Extender.
Il ne reste plus qu’a écrire la méthode « DataBinding() » dans le TargetControlProperties qui va simplement appeler l’EventHandler de Binding (C’est à ce moment dans l’exemple du début que la propriété Tag de l’Extender est affecté) :
private
EventHandlerList _eventHandlerList =
new EventHandlerList();
public void DataBind(
object sender,
EventArgs e)
{
((
EventHandler)_eventHandlerList[
this])(
this,
EventArgs.Empty);
}
public
event EventHandler DataBinding
{
add
{
_eventHandlerList.AddHandler(
this,
value);
}
remove
{
_eventHandlerList.RemoveHandler(
this,
value);
}
}
public
Control BindingContainer
{
get
{
return base.TargetControl.BindingContainer;
}
}
Voila, les propriétés de l’Extender Atlas sont maintenant Bindable dans des contrôles conteneurs.
Vous pouvez rajouter cette fonctionnalité dans vos Extenders ou en modifiant ceux existants grâce aux sources sur
CodePlex,
mais sachez que cette fonctionnalité sera intégrée à l’Extender de base donc pour tous les Extender mais ne sortira qu’à la prochaine version officiel des ToolKit après la 1.0.060616.0 qui sort début de semaine.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :