Solved

Can't switch modes with DetailsView TemplateField?  (Anyone?  Bueller?)

Posted on 2008-06-23
10
907 Views
Last Modified: 2013-11-07
(This is the third time I've re-posted this question, trying to get attention.  I'm pretty surprised I can't get anyone to look at it.  I've wrapped it up as best as I can, nobody will even try my cut-and-paste code and say "works for me" or "yeah that's weird"??  There appears to be lots of knowledge on this site on DetailsViews, and I'm having some stubborn trouble, and I'm sure it's something simple I'm not doing.  Please, if you're an expert on this stuff and don't like this question, let me know how to rephrase it... or if you can suggest alternate approaches...  )

Hey.  I'm having trouble with switching modes in my DetailsView.  I'm not using a real database, just my own DataTable (which I think should work fine).  It works fine (switching between modes, saving data or not) with BoundFields and CheckBox fields, but when I create my own TemplateField (with a combo box), the controls seem to disappear.

I've provided cut-and-paste code to show the problem.  Create a new webform and (just tested this, works fine):

a) Drop DetailsView1 on it
b) Replace the VB code behind it with the code below.
c) Add the attribute EnableEventValidation="false" to the Page item on the page source, mine looks like:

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="FormTest3.aspx.vb" Inherits="FormTest3" EnableEventValidation="false"%>

And you'll see the problem.  Change the data and click "update", and the data saves (into my DataTable, where I can process it on the server), or cancel and it doesn't save.  Then go back to Edit mode and so on.  *Except* for my TemplateField, which seems to go blank on any mode change.

Somehow I'm missing something special that is needed to keep my TemplateField active, an event handler or something.

If anyone has ANY ideas, I'd love to hear them.  This problem has been my showstopper for several days now.  Thanks VERY much.
Partial Class FormTest2
    Inherits System.Web.UI.Page
 
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
 
        If Not IsPostBack Then
 
            ' ****************************************
            '
            ' if I start it out in edit mode, then the combo box template displays
            ' fine, with the dummy defined values
            '
            ' if I start it out in readonly mode, then the label template displays
            ' fine, with the dummy text
            '
            ' but in either case, when I switch to the other mode, the 
            ' template does not display, it's just a blank field
            '
            ' (I do have to set Page EnableEventValidation="false" for some 
            ' reason, or the combo box belches)
            ' 
            ' (was going to add code to set/read the combo box, but for now 
            ' just can't get it to display)
            '
            ' ****************************************
 
            DetailsView1.DefaultMode = DetailsViewMode.Edit
            'DetailsView1.DefaultMode = DetailsViewMode.ReadOnly
 
            ' ****************************************
            ' build a datatable
            ' add columns 'Field1' and 'Field2'
            ' ****************************************
 
            Dim dt As New Data.DataTable
            Session("stored_datatable") = dt
 
            Dim bc As New Data.DataColumn
            bc.ColumnName = "Field1"
            dt.Columns.Add(bc)
 
            Dim bc2 As New Data.DataColumn
            bc2.ColumnName = "Field2"
            dt.Columns.Add(bc2)
 
            Dim bc3 As New Data.DataColumn
            bc3.ColumnName = "Field3"
            dt.Columns.Add(bc3)
 
            Dim bc4 As New Data.DataColumn
            bc4.ColumnName = "Field4"
            dt.Columns.Add(bc4)
 
            ' ****************************************
            ' build the details view to match
            ' ****************************************
 
            With DetailsView1
 
                .AutoGenerateRows = False
                .AutoGenerateEditButton = True
 
                Dim dcf As New BoundField
                dcf.DataField = "Field1"
                dcf.HeaderText = "Field1"
                .Fields.Add(dcf)
 
                Dim dcf2 As New BoundField
                dcf2.DataField = "Field2"
                dcf2.HeaderText = "Field2"
                .Fields.Add(dcf2)
 
                Dim dcf3 As New CheckBoxField
                dcf3.DataField = "Field3"
                dcf3.HeaderText = "Field3"
                .Fields.Add(dcf3)
 
                Dim dcf4 As New TemplateField()
 
                Dim temp_cmb As New TemplateComboBox()
                Dim temp_lbl As New TemplateLabel()
 
                dcf4.ItemTemplate = temp_lbl
                dcf4.EditItemTemplate = temp_cmb
                dcf4.HeaderText = "Field4"
                .Fields.Add(dcf4)
 
            End With
 
            ' ****************************************
            ' add a single row to the datatable
            ' ****************************************
 
            dt.Rows.Add("data1", "data2", True, 3)
 
            ' ****************************************
            ' and bind
            ' ****************************************
 
            DetailsView1.DataSource = dt
            DetailsView1.DataBind()
 
        End If
 
    End Sub
 
    Protected Sub DetailsView1_ModeChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewModeEventArgs) Handles DetailsView1.ModeChanging
 
        ' ****************************************
        ' handle the mode change
        ' rebind to the source table
        ' ****************************************
 
        Dim dv As DetailsView = sender
 
        Dim dt As Data.DataTable = Session("stored_datatable")
 
        dv.DataSource = dt
 
        Select Case e.NewMode
 
            Case DetailsViewMode.ReadOnly : dv.ChangeMode(DetailsViewMode.ReadOnly)
            Case DetailsViewMode.Edit : dv.ChangeMode(DetailsViewMode.Edit)
            Case DetailsViewMode.Insert : dv.ChangeMode(DetailsViewMode.Insert)
 
        End Select
 
        dv.DataBind()
 
    End Sub
 
    Protected Sub DetailsView1_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewUpdateEventArgs) Handles DetailsView1.ItemUpdating
 
        ' ****************************************
        ' handle the item update
        ' must admit: don't know why all this is necessary, got it from EE
        ' maybe it will become clear later
        ' ****************************************
 
        Dim dv As DetailsView = sender
        Dim dt As Data.DataTable = Session("stored_datatable")
 
        For i As Integer = 0 To dv.Fields.Count - 1
 
            Dim cn As DataControlFieldCell = dv.Rows(i).Cells(0)
            dv.Fields(i).ExtractValuesFromCell(e.Keys, cn, DataControlRowState.Normal, True)
 
            Dim ce As DataControlFieldCell = dv.Rows(i).Cells(1)
            dv.Fields(i).ExtractValuesFromCell(e.NewValues, ce, DataControlRowState.Edit, False)
 
        Next
 
        Dim cnt As Integer = 0
 
        For Each key As String In e.NewValues.Keys
            dt.Rows(0).Item(cnt) = e.NewValues(key)
            cnt += 1
        Next
 
        dv.DataSource = dt
        dv.ChangeMode(DetailsViewMode.ReadOnly)
        dv.DataBind()
 
    End Sub
 
    ' ****************************************
    ' my template classes for the combo box
    ' ****************************************
 
    Public Class TemplateComboBox
 
        Implements ITemplate
 
        Dim WithEvents m_combobox As New DropDownList
 
        Public Sub New()
 
            Dim L1 As New ListItem
            L1.Text = "Choice1"
            L1.Value = "1"
            m_combobox.Items.Add(L1)
            Dim L2 As New ListItem
            L2.Text = "Choice2"
            L2.Value = "2"
            m_combobox.Items.Add(L2)
 
        End Sub
 
        Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
 
            container.Controls.Add(m_combobox)
 
        End Sub
 
    End Class
 
    Public Class TemplateLabel
 
        Implements ITemplate
 
        Dim m_label As New Label
 
        Public Sub New()
 
            m_label.Text = "dummy text"
 
        End Sub
 
        Public Sub InstantiateIn(ByVal container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
 
            container.Controls.Add(m_label)
 
        End Sub
 
    End Class
 
End Class

Open in new window

0
Comment
Question by:riceman0
  • 5
  • 4
10 Comments
 
LVL 33

Expert Comment

by:raterus
ID: 21851439
You have the dynamic control blues, that is any controls you create dynamically, you have to rebuild them on each postback.

Basically if you want this to work, you have to run the following code (below) on each postback in page_load to rebuild the controls in the DetailsView.


            With DetailsView1
 
                .AutoGenerateRows = False
                .AutoGenerateEditButton = True
 
                Dim dcf As New BoundField
                dcf.DataField = "Field1"
                dcf.HeaderText = "Field1"
                .Fields.Add(dcf)
 
                Dim dcf2 As New BoundField
                dcf2.DataField = "Field2"
                dcf2.HeaderText = "Field2"
                .Fields.Add(dcf2)
 
                Dim dcf3 As New CheckBoxField
                dcf3.DataField = "Field3"
                dcf3.HeaderText = "Field3"
                .Fields.Add(dcf3)
 
                Dim dcf4 As New TemplateField()
 
                Dim temp_cmb As New TemplateComboBox()
                Dim temp_lbl As New TemplateLabel()
 
                dcf4.ItemTemplate = temp_lbl
                dcf4.EditItemTemplate = temp_cmb
                dcf4.HeaderText = "Field4"
                .Fields.Add(dcf4)
 
            End With

Open in new window

0
 

Author Comment

by:riceman0
ID: 21851515
Thanks very much for the answer!!!

Will play around with that further, but when I try that on every reload it seems to add more and more fields to the control... which seems to suggest it does not need rebuilding... ?  Is this still the "dynamic control blues" (thanks for the concept) you're talking about?  After all I actually dropped the DetailsView in the designer, and it is visible in the ASP source, not instantiated in the code behind (it's just my DataTable that is created in the code behind).  Doesn't that make it statically created?

I will play around right now with recreating my TemplateField on every load though.  Maybe that element defies client-side persistence or something.  Of course I just sort of made up those words.
0
 
LVL 33

Expert Comment

by:raterus
ID: 21851575
Actually, I was baffled that those other controls weren't disappearing, usually it's all or nothing.  I figured you still were down with the blues (the most common issue, by far, I see on this boards)  How does your .aspx page look, specifically the DetailsView?

No, any control you instantiate itself, and add to another control's controls section is a "dynamic" control.  The only thing I can gather about your issue is that the DetailsView can actually persist the very basic of columns.  Since the Templatefield is a bit more uncommon, it doesn't mess with that.  I dunno, I've never tested it and if it is like this, I've never seen another control act in this manner.
0
Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

 

Author Comment

by:riceman0
ID: 21851686

In the designer (if that's what you mean...) the DetailsView is just an empty control, the default three fields.

But it's funny, on inspection the DetailsView seems to retain nearly all of its properties on postbacks, like .AutoGenerateRows remains false, and it keeps the 4 fields (even though I only define them on the original load).  The fourth field even remains a TemplateField -- however both the EditItemTemplate and ItemTemplate properties of the TemplateField have vaporized to 'Nothing.'  Seems like everything is persistent but those template pointers.  I'll try to refresh those template references every time (although I have a faint recollection of trying that before to no avail, and concluded something more fundamental was wrong...)
0
 
LVL 33

Expert Comment

by:raterus
ID: 21851945
Switch to the HTML view and find something like <asp:DetailsView ...>  Post everything around that.  I think your designer is already adding these fields that are retaining their value, which is expected..
0
 

Author Comment

by:riceman0
ID: 21851957

As empty as can be, right?  That runat=server is interesting, although I assume that's default...
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:DetailsView ID="DetailsView1" runat="server" Height="50px" Width="125px">
        </asp:DetailsView>
    
    </div>
    </form>
</body>
</html>

Open in new window

0
 
LVL 33

Accepted Solution

by:
raterus earned 400 total points
ID: 21855259
Yeah, that is perfectly fine.

I "guess" detailsview actually persists the controls you add dynamically, strange, but I stepped through the code and it's doing exactly that.

Regardless, I was able to fix your missing text problem by adding this code (below).  Take note of the .Fields.Clear() method I'm using too.
        With DetailsView1
            .Fields.Clear()
            .AutoGenerateRows = False
            .AutoGenerateEditButton = True
 
            Dim dcf As New BoundField
            dcf.DataField = "Field1"
            dcf.HeaderText = "Field1"
            .Fields.Add(dcf)
 
            Dim dcf2 As New BoundField
            dcf2.DataField = "Field2"
            dcf2.HeaderText = "Field2"
            .Fields.Add(dcf2)
 
            Dim dcf3 As New CheckBoxField
            dcf3.DataField = "Field3"
            dcf3.HeaderText = "Field3"
            .Fields.Add(dcf3)
 
            Dim dcf4 As New TemplateField()
 
            Dim temp_cmb As New TemplateComboBox()
            Dim temp_lbl As New TemplateLabel()
 
            dcf4.ItemTemplate = temp_lbl
            dcf4.EditItemTemplate = temp_cmb
            dcf4.HeaderText = "Field4"
            .Fields.Add(dcf4)
 
        End With

Open in new window

0
 

Assisted Solution

by:NorthReno
NorthReno earned 100 total points
ID: 21860491
Have you tried building all of your controls and assigning all of the attributes in the ASPX page?  I have had pretty good luck with my details view.  The problems came when I tried adding things on the fly.  I haven't tried changing the modes dynamically as I always want it to be in insert mode.

It is a rather complex Details view complete with ItemTemplates, and InsertTemplates.  By the way, what modes are you using? Edit and Insert?  If so, I believe that you will need both EditTemplates and InsertTemplates.  Take a look at my snippit below and see if it is of any help.

At the beginning,  I set all of the values I have to have on start up, including the DefaultMode.  For each control everything is also statically set.  During processing, I have certain fields I enable and disable, turn visible and invisible... dynamically - regardless of postback status.

Hope it helps.
       <asp:DetailsView ID="dtvReceiptsEntry" 
                         runat="server" 
                         Enabled="false"
                         AutoGenerateRows="false"
                         Height="33px" 
                         Width="45%"
                         DefaultMode="Insert"
                         BackColor="#DEBA84" 
                         BorderColor="#DEBA84" 
                         BorderStyle="None" 
                         BorderWidth="1px" 
                         CellPadding="2" 
                         CellSpacing="1" GridLines="Both">
 
            <FooterStyle BackColor="#F7DFB5" ForeColor="#8C4510" />
            <RowStyle BackColor="#FFF7E7" ForeColor="#8C4510" />
            <PagerStyle ForeColor="#8C4510"  />
            <HeaderStyle BackColor="#A55129" Font-Bold="True" ForeColor="White" />
            <EditRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="White" HorizontalAlign="Left"  />
            <Fields>
                <asp:TemplateField HeaderText="Transporter FEIN">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtCarrierFEIN"   
					                 runat="server" 
                                     CssClass="Bod8"
					                 Width="80px">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Transporter Name">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtCarrierName" 
                                     CssClass="Bod8"
                                     runat="server"
                                     width="250px">
                        </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Mode Type">
                    <InsertItemTemplate>
                       <asp:DropDownList ID="ddlModeType" 
                                          runat="server" 
                                          DataSourceID="odsuf_rtdata_mfmo"
                                          DataTextField="data_txt" 
                                          DataValueField="key_txt"  
                                          SelectedValue='<%# Eval ("MODE_TY") %>' 
					                      Width="150px" 
                                          CssClass="Bod8">
                        </asp:DropDownList>
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Origin City">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtOrigCity" 
					                 runat="server" 
					                 Width="250px"
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Origin State">
                    <InsertItemTemplate>
                        <asp:DropDownList ID="ddlOrigState" 
			                              runat="server" 
			                              Width="100px"
			                              CssClass="Bod8"  
			                              DatasourceID="odsuf_rtdata_gsta" 
			                              DataTextField="data_txt" 
			                              DataValueField="key_txt" 
			                              SelectedValue='<%# Eval("Orig State") %>'>
			            </asp:DropDownList>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Dest City">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtDestCity"    
					                 runat="server" 
					                 Width="250px"
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Dest State">
                    <InsertItemTemplate>
                        <asp:DropDownList ID="ddlDestState" 
					                      runat="server" 
					                      Width="100px"
					                      CssClass="Bod8" 
					                      DatasourceID="odsuf_rtdata_gsta" 
						                  DataTextField="data_txt" 
						                  DataValueField="key_txt" 
						                  SelectedValue='<%# Eval("Dest State") %>'>
						</asp:DropDownList>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Seller's FEIN">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtSellerFEIN" 
					                 runat="server" 
					                 Width="80px"
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Received From">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtRcvdFrom" 
					                 runat="server" 
					                 Width="250px"
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Date Received">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtDateRcvd" 
					                 runat="server" 
					                 Width="80px"
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="BOL/Manifest">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtBOL" 
					                 runat="server" 
					                 Width="100px"
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Net Gallons">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtNetGal" 
					                 runat="server" 
					                 Width="80px"
					                 CssClass="Bod8">
					    </asp:TextBox>                    
 
					</InsertItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Gross Gallons">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtGrossGal" 
					                 runat="server" 
					                 Width="80px" 
					                 CssClass="Bod8">
					    </asp:TextBox>
 
					   
                    </InsertItemTemplate>                
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Billed Gallons">
                    <InsertItemTemplate>
                        <asp:TextBox ID="txtBillGal" 
					                 runat="server" 
					                 Width="80px" 
					                 CssClass="Bod8">
					    </asp:TextBox>
 
                    </InsertItemTemplate>                
                </asp:TemplateField>
            </Fields>
 
        </asp:DetailsView>

Open in new window

0
 

Author Comment

by:riceman0
ID: 21907536
By the way I had to set this aside for a few days (fighting a fire on a different project) but I will get back to it  ASAP, and I do appreciate the help!
0
 

Author Comment

by:riceman0
ID: 22149312
Haven't licked this problem yet, I'm just closing this out to award the points to the deserving parties.  Will post the solution when I achieve it.
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question