ASP.NET ListView with identical markup in EditItemTemplate and InsertItemTemplate
Asked Answered
B

2

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?

Boarder answered 2/2, 2010 at 14:34 Comment(1)
According to this post: http://forums.asp.net/p/1344635/2729853.aspx, it's quite tricky to do it declaratively. It would be easier to do create the templates from the code-behind.Bilberry
B
2

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.

Boarder answered 4/2, 2010 at 20:15 Comment(0)
E
2

I'm very late to the party, but for anyone looking for a declarative solution, I ended up doing the following (control is my FormView):

if (control.EditItemTemplate == null)
{
    control.EditItemTemplate = control.InsertItemTemplate;
}

And for the template:

<InsertItemTemplate>

    ... template ...

    <asp:LinkButton Text="Insert" CommandName="Insert" runat="server" 
                    Visible='<%# Container.ItemType == ListViewItemType.InsertItem %>' />
    <asp:LinkButton Text="Update" CommandName="Update" runat="server"
                    Visible='<%# Container.ItemType == ListViewItemType.DataItem %>' />
    <asp:LinkButton Text="Cancel" CommandName="Cancel" runat="server" 
                    Visible='<%# Container.ItemType == ListViewItemType.DataItem %>' />
</InsertItemTemplate>

Where the interesting bit is obviously: Container.ItemType == ListViewItemType.DataItem (and others). This correctly sets the visibility of the buttons according to the template type.

Erving answered 20/5, 2015 at 10:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.