Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expose an ITemplate through a User Control?

Tags:

To make certain form creation easier, we use a modified Formview control that is inside a User Control. This User Control is for a grid and a FormView, you can choose an item in the grid, and a FormView is presented in a modal for viewing/editing:

<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>

In a page, the control looks like this:

<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>

The problem is the EditItemTemplate we use. The only way I can figure out how to hook it up is to have an ITemplate in the TabGrid control and apply the reference in OnInit:

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

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

The problem with this is that because the reference is to an object in the user control, the EditItemTemplate reference that ties to the dictionary entries in FormView for changes are destroyed, so when you get the dictionary of changes sent to the datasource, they're empty on every postback.

The I2:ILDataSource used here is a custom implementation closest to ObjectDataSource. Instead of a generic object call, it directly calls a GetEntity() in the page (or user control in this case) and a UpdateEntity(obj Entity) to save. Since it's a very specific scenario, we can eliminate 90% of the code in ObjectDataSource.

What I want to be able to do is point the <EditItemTemplate> in the <I2C:TabGrid> directly to the <EditItemTemplate> of the <I2:FormView> inside. Is this possible, or anyone have suggestions of another route to go?

Note: I tried exposing the EditItemTemplate on FVSubForm as a proxy property, but this didn't work because the property is set on the user control before the child control is created, so FVSubForm is null. If this can be worked around, I'm certainly all ears.

like image 559
Nick Craver Avatar asked Sep 14 '09 15:09

Nick Craver


1 Answers

One thing you need to do is mark your ITemplate property as supporting two-way databinding:

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

Without this, ASP.NET will not generate the proper code for the page that allows Bind() expressions to work.

I'm not sure if that's all you need, but that's something to try.

David

like image 114
David Ebbo Avatar answered Oct 02 '22 21:10

David Ebbo