views:

351

answers:

1

I have a ListView that includes an EditItemTemplate and an InsertItemTemplate. The two forms share almost all of their markup. For example:

<asp:listview runat="server" ... >
   <layouttemplate>...</layouttemplate>
   <itemtemplate>
      <p><%#Eval("Name")%></p>
      <p><%#Eval("Title")%></p>
       ...
   </itemtemplate>
   <insertitemtemplate>
      <p>Name: <asp:textbox runat=server text='<%#Bind("Name")%>' /></p>
      <p>Title: <asp:textbox runat=server text='<%#Bind("Title")%>' /></p>
      ...
      <asp:button runat=server commandname="Insert" text="Save" />
   </insertitemtemplate>
   <edititemtemplate>
      <p>Name: <asp:textbox runat=server text='<%#Bind("Name")%>' /></p>
      <p>Title: <asp:textbox runat=server text='<%#Bind("Title")%>' /></p>
      ...
      <asp:button runat=server commandname="Update" text="Save" />
   </edititemtemplate>
</asp:listview>

Of course, in reality there's a lot going on in the insert and edit templates (lots of fields, with formatting, validation, etc.), and I hate to have to maintain the same markup twice.

My first thought was to move all the shared markup to a user control (.ascx):

   <insertitemtemplate>
      <custom:myform runat=server />
      <asp:button runat=server commandname="Insert" text="Save" />
   </insertitemtemplate>
   <edititemtemplate>
      <custom:myform runat=server />
      <asp:button runat=server commandname="Update" text="Save" />
   </edititemtemplate>

Unfortunately, the two-way binding (text='<%#Bind("Foo")%>') only works one way when the form is in a user control (it doesn't persist the data from the controls back to the database).

An alternative would be to move all the shared markup to an include file. Server-side includes are a throwback to classic ASP, but they still work in ASP.NET and can be useful in situations like this, because the contents of the include file are treated just like markup that's right on the page.

But include files are still a little hokey, and have their disadvantages (e.g. VisualStudio isn't very comfortable with them). Is there an alternative?

A: 

I've ended up making a custom ListView that makes this straightforward. If there is no InsertItemTemplate, then the EditItemTemplate is used for both:

    Private Sub ListView_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
        If Me.InsertItemTemplate Is Nothing Then
            Me.InsertItemTemplate = Me.EditItemTemplate
        End If
    End Sub

I've also created a custom "save" button that switches its commandname between "Update" and "Insert" as appropriate:

    Private Sub SaveLinkButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        Dim _ListView As Controls.ListView = GetListView()
        If _ListView IsNot Nothing Then
            If Me.BindingContainer Is _ListView.EditItem Then
                Me.CommandName = "Update"
            Else
                Me.CommandName = "Insert"
            End If
        End If
    End Sub

(The GetListView function above just walks up the button's parents until it finds a ListView.)

That's it - hope this is helpful to someone.

Herb Caudill