Sharing FormView Edit and insert templates to avoid duplicate markup

If you used the FormView control ,I’m sure that you had modified it’s generated Edit and Insert templates(like adding calendar for the date fields , changing the textboxes that are bound to the foreign key columns with a dropdown list,adding validation controls to some of the fields , apply some masks … etc .

The Problem:

The problem is that if you need to use edit and insert functionalities in the FormView control, you will have to modify both of it’s edit and insert templates.also will you need to make sure that any change on one of the templates  will be reflected on the other templates.

Consider the following example:

You are working with the orders table of the Northwind database and you want to use the FormView control to add/edit order information's.

The FormView Edit and Insert templates will looks like this (assume you added calendar extender to the data fields) :

<asp:FormView ID="FormView1" runat="server">
    <EditItemTemplate>
=>  Edit template  markup here ...
        <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
            Text="Update" />
        &nbsp;<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False"
            CommandName="Cancel" Text="Cancel" />
    </EditItemTemplate>
    <InsertItemTemplate>
 =>    insert template  markup here ...(same as edit template markup)
        <asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert"
            Text="Insert" />
        &nbsp;<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False"
            CommandName="Cancel" Text="Cancel" />
    </InsertItemTemplate>
</asp:FormView>

As you may noticed, The Edit and Insert templates both contains the same code.As an experienced developer, you should always avoiding duplicate code.This is to increase the maintainability of the code.

 

The Solution: 

There is many solutions for the mentioned problem ,Assume that you are using the FormView to edit/add northwind order object.To avoid duplicating the same markup in both templates , you can move the shared markup from the FormView Edit and Insert templates to a separate usercontrol and place this usercontrol in both templates.

Something like this :

1 <EditItemTemplate>
2 <uc1:OrderEditFields ID="OrderEditFields1" runat="server" />
3 <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update"
4 Text="Update" />
5 &nbsp;<asp:LinkButton ID="UpdateCancelButton" runat="server" CausesValidation="False"
6 CommandName="Cancel" Text="Cancel" />
7 </EditItemTemplate>
8 <InsertItemTemplate>
9 <uc1:OrderEditFields ID="OrderEditFields1" runat="server" />
10 <asp:LinkButton ID="InsertButton" runat="server" CausesValidation="True" CommandName="Insert"
11 Text="Insert" />
12 &nbsp;<asp:LinkButton ID="InsertCancelButton" runat="server" CausesValidation="False"
13 CommandName="Cancel" Text="Cancel" />
14 </InsertItemTemplate>

Of course,The OrderEditFields UserControl code will contains the code that was moved from the FormView Edit /Insert templates ( but without the command buttons which are different for each template)

1 OrderID:
2 <asp:Label ID="OrderIDLabel1" runat="server" Text='<%# Eval("OrderID") %>' />
3 <br />
4 CustomerID:
5 <asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="SqlDataSource1"
6 DataTextField="CompanyName" DataValueField="CustomerID" SelectedValue='<%# Bind("CustomerID") %>'>
7 </asp:DropDownList>
8 <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
9 SelectCommand="SELECT [CustomerID], [CompanyName] FROM [Customers]" ></asp:SqlDataSource>
10 <br />
11 EmployeeID:
12 <asp:DropDownList ID="DropDownList2" runat="server" DataSourceID="SqlDataSource2"
13 DataTextField="FullName" DataValueField="EmployeeID" SelectedValue='<%# Bind("EmployeeID") %>'>
14 </asp:DropDownList>
15 <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
16 SelectCommand="SELECT EmployeeID, FirstName + ' ' + LastName AS FullName FROM Employees">
17 </asp:SqlDataSource>
18 <br />
19 OrderDate:
20 <asp:TextBox ID="OrderDateTextBox" runat="server" Text='<%# Bind("OrderDate") %>' />
21 <AjaxToolkit:CalendarExtender ID="OrderDateTextBox_CalendarExtender" runat="server"
22 Enabled="True" TargetControlID="OrderDateTextBox">
23 </AjaxToolkit:CalendarExtender>
24 <br />
25 RequiredDate:
26 <asp:TextBox ID="RequiredDateTextBox" runat="server" Text='<%# Bind("RequiredDate") %>' />
27 <AjaxToolkit:CalendarExtender ID="RequiredDateTextBox_CalendarExtender" runat="server"
28 Enabled="True" TargetControlID="RequiredDateTextBox">
29 </AjaxToolkit:CalendarExtender>
30 <br />
31 ShippedDate:
32 <asp:TextBox ID="ShippedDateTextBox" runat="server" Text='<%# Bind("ShippedDate") %>' />
33 <AjaxToolkit:CalendarExtender ID="ShippedDateTextBox_CalendarExtender" runat="server"
34 Enabled="True" TargetControlID="ShippedDateTextBox">
35 </AjaxToolkit:CalendarExtender>
36 <br />
37 ShipVia:
38 <asp:TextBox ID="ShipViaTextBox" runat="server" Text='<%# Bind("ShipVia") %>' />
39 <br />
40 Freight:
41 <asp:TextBox ID="FreightTextBox" runat="server" Text='<%# Bind("Freight") %>' />
42 <br />
43 ShipName:
44 <asp:TextBox ID="ShipNameTextBox" runat="server" Text='<%# Bind("ShipName") %>' />
45 <br />
46 ShipAddress:
47 <asp:TextBox ID="ShipAddressTextBox" runat="server" Text='<%# Bind("ShipAddress") %>' />
48 <br />
49 ShipCity:
50 <asp:TextBox ID="ShipCityTextBox" runat="server" Text='<%# Bind("ShipCity") %>' />
51 <br />
52 ShipRegion:
53 <asp:TextBox ID="ShipRegionTextBox" runat="server" Text='<%# Bind("ShipRegion") %>' />
54 <br />
55 ShipPostalCode:
56 <asp:TextBox ID="ShipPostalCodeTextBox" runat="server" Text='<%# Bind("ShipPostalCode") %>' />
57 <br />
58 ShipCountry:
59 <asp:TextBox ID="ShipCountryTextBox" runat="server" Text='<%# Bind("ShipCountry") %>' />
60

 

Hope it Helps

6 Comments

  • great article! I'm a newbie to asp.net. one question i have is where are you putting your datasource? Is it in the usercontrol?

  • Hi Bm,
    The i assumed that the data source will be placed in the page in which the formview is placed.

  • Great Article! Make perfect sense to me.

    I created the controls as you specified above, and it populates the controls like a charm. I'm using an Object Data Source, btw.

    However, when the UpdateMethod is called, the object passed in blank. I created a handler for the OnUpdating event, and indeed the object passed into the method is defaulted (ie - created with default constructor), but not populated.

    If I move the controls from the user control to the form view edit template, it populates.

    I'm sure its some sort of data binding issue between the ODS and the UserControl, but I haven't been able to find a solution.

    Have you run into this issue, and if so, do you have a solution?

    Using ASP.Net v3.5, C#, Form View and ODS on aspx file, and user control as you specify.

    I can post code if that helps.

    Thanks!


  • I'm trying the same thing with an ObjectDataSource on the page, but it simply doesn't work.

    What does work is one-way binding. The data is displayed, but when doing an update the data isn't available.

    Any resolution?

  • Please test the code before posting in blogs like this.

    As we found issues with 2 way binding, thus this article doesnt make any sense at all.

  • Thanks for the idea. It helped :)

Comments have been disabled for this content.