2009-09-14 10 views
5

Pour faciliter la création d'un formulaire, nous utilisons un contrôle FormView modifié dans un contrôle utilisateur. Cet utilisateur contrôle est pour une grille et un FormView, vous pouvez choisir un élément dans la grille, et un FormView est présenté dans un modal pour la visualisation/édition:Comment exposer un ITemplate via un contrôle utilisateur?

<I2CL:Grid runat="server" ID="Grid" OnSelecting="Selecting" ShowCreate="true" /> 
<I2:Modal ID="SFModal" runat="server" UpdateMode="Conditional"> 
<ContentTemplate> 
    <I2:FormView runat="server" ID="FVSubForm" DefaultMode="Edit" DataSourceID="DSSubForm" /> 
    <I2:ILDataSource ID="DSSubForm" runat="server" /> 
</ContentTemplate> 
</I2:Modal> 

Dans une page, le contrôle ressemble à ceci:

<I2C:TabGrid ID="TG" runat="server" Property="ParentProperty"> 
    <Columns> 
    <I2:Column Header="Column 1" DataSource="Column1" /> 
    <I2:Column Header="Column 2" DataSource="Column2" /> 
    </Columns> 
    <EditItemTemplate> 
    <I2Form:Dropdown ID="Col1" runat="server" SelectedValue='<%# Bind("Column1") %>' List="Column1Options" /> 
    <I2Form:Textbox ID="Col2" runat="server" Text='<%# Bind("Column2") %>' /> 
    </EditItemTemplate> 
</I2C:TabGrid> 

Le problème est le EditItemTemplate que nous utilisons. La seule façon que je peux comprendre comment le brancher est d'avoir une ITemplate dans le contrôle TabGrid et appliquer la référence en OnInit:

[PersistenceMode(PersistenceMode.InnerProperty), 
TemplateContainer(typeof(FormView))] 
public ITemplate EditItemTemplate { get; set; } 

protected override void OnInit(EventArgs e) 
{ 
base.OnInit(e); 
FVSubForm.EditItemTemplate = EditItemTemplate; 
} 

Le problème est que, parce que la référence est à un objet dans la contrôle utilisateur, la référence EditItemTemplate liée aux entrées de dictionnaire dans FormView pour les modifications est détruite. Ainsi, lorsque vous obtenez le dictionnaire des modifications envoyées à la source de données, elles sont vides à chaque publication.

La source I2: ILDataSource utilisée ici est une implémentation personnalisée la plus proche de ObjectDataSource. Au lieu d'un appel d'objet générique, il appelle directement un GetEntity() dans la page (ou le contrôle utilisateur dans ce cas) et un UpdateEntity(obj Entity) pour enregistrer. Comme il s'agit d'un scénario très spécifique, nous pouvons éliminer 90% du code dans ObjectDataSource.

Ce que je veux être en mesure de faire est le point le <EditItemTemplate> dans le <I2C:TabGrid> directement au <EditItemTemplate> du <I2:FormView> intérieur. Est-ce possible, ou quelqu'un a des suggestions d'un autre itinéraire à parcourir? Remarque: J'ai essayé d'exposer EditItemTemplate sur FVSubForm en tant que propriété de proxy, mais cela n'a pas fonctionné car la propriété est définie sur le contrôle utilisateur avant la création du contrôle enfant, donc FVSubForm est null. Si cela peut être travaillé, je suis certainement tout ouïe.

Répondre

5

Une chose que vous devez faire est de marquer votre propriété ITemplate que le soutien databinding dans les deux sens:

[TemplateContainer (typeof (FormView), System.ComponentModel.BindingDirection.TwoWay)]

Sans cela, ASP.NET ne générera pas le code approprié pour la page qui permet aux expressions Bind() de fonctionner.

Je ne sais pas si c'est tout ce dont vous avez besoin, mais c'est quelque chose à essayer.

David

+0

Merci pour la suggestion ... mais la situation est la suivante: le ITemplate lui-même dans le contrôle de l'utilisateur ne soit pas lié, il est le ITemplate sur le contrôle FormView qu'il est affecté à que toute liaison se produit sur ... il possède les attributs de liaison appropriés. J'ai essayé de toute façon, mais aucune différence sur le résultat final (les valeurs de mise à jour vides reviennent) –

+0

Bien que ce n'était pas le problème direct, c'était un proxy contraignant ne se propageant pas, le ITemplate auquel le contrôle utilisateur était lié ne prenait pas correctement en charge Liaison bi-directionnelle ... puisque la grille n'est pas directement modifiable, je n'ai jamais remarqué que seul Eval() se comportait dans tout ce qui est en dessous. Merci David, la bonté pointe vers toi! –

+0

Merci Nick. J'aurais aimé en faire une condition d'erreur pour essayer d'utiliser Bind() dans des scénarios où il ne fera rien parce que le ITemplate n'est pas correctement marqué. Si vous êtes curieux, jetez un oeil au code généré pour la page avec et sans le drapeau TwoWay.Avec le drapeau, vous verrez apparaître une nouvelle méthode __ExtractValues__, qui a toute la logique pour faire fonctionner Bind(). –

Questions connexes