Solved

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

Posted on 2008-06-23
10
894 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
 

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
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

In my previous two articles we discussed Binary Serialization (http://www.experts-exchange.com/A_4362.html) and XML Serialization (http://www.experts-exchange.com/A_4425.html). In this article we will try to know more about SOAP (Simple Object Acces…
For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

746 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now