[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

BindingManagerBase .addNew Method is only editing current record not inserting a new one

Posted on 2006-05-02
14
Medium Priority
?
1,020 Views
Last Modified: 2008-01-09
I am writing a form based appliciation to allow a user to enter and edit demographic information:

The problem I am having is a very odd one as I know this has worked for me before, I just can't figure out why it won't now.  What is happening is that I am calling the bindingmanagerbase.addnew method when the user clicks the btnAdd button.  (I have the code for that below)  After calling the .addnew it will place the next incriment for the primary surrogate key in the lblID label that the primary key is bound to.  This portion appears to work properly until you click the btnEnd button (code below).  For whatever reason, the .addnew method is not doing it's job and instead is just enabling edit of the record you were last viewing.  Just a curious, eventhough the lblID.text is changed, it is not updating that field at all.  Please help as I have some people waiting on this and I have so much more work to do!


    Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
        If btnAdd.Text = "Add Person" Then
            unlockBoxes()
            disableNav()
            setButtonForEdit()
            bmFound.EndCurrentEdit()
            Dim myTable As DataTable
            myTable = DsFound1.Tables("Person")

            Dim objMax As Object
            objMax = myTable.Compute("MAX(Person_ID)", "") + 1
            bmFound.AddNew()
            lblID.Text = objMax
            clearFields()

        End If
    End Sub

    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        Try

        bmFound.EndCurrentEdit()
        daPerson.Update(DsFound1)
        DsFound1.AcceptChanges()
        lockBoxes()
        enableNav()
            resetButtonsAfterEdit()

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        'Position_Changed(sender, e)
    End Sub
0
Comment
Question by:Bull_81073
  • 8
  • 5
14 Comments
 
LVL 34

Expert Comment

by:Sancler
ID: 16587274
Try adding

            bmFound.Position = bmFound.Count - 1
 
after

            bmFound.AddNew()

Roger
0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16588104
That made no difference!  It is behaving exactly the same way :-(
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16589157
It sounds like there may be some conflict in the data-bindings somewhere.  If so, it's very difficult to spot at a distance.  But you say "The problem I am having is a very odd one as I know this has worked for me before, I just can't figure out why it won't now."  Have you made any change to any of the data-bindings?

Roger
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Author Comment

by:Bull_81073
ID: 16590495
No I haven't,  the controls are bound from the Data Bindings properties and I am not setting them programaticially.  Could you be more specific about where I might need to start looking?
0
 
LVL 34

Accepted Solution

by:
Sancler earned 1640 total points
ID: 16591777
The sort of data-binding problem that I have seen producing this symptom - of the binding manager not actually recognising the new record it creates - is where

1)  a control (specifically a combo or list box) is bound to two datasources like this

   combobox.DataSource = MyLookUpTable
   combobox.DisplayMember = "LookUpDescription"
   combobox.ValueMember = "LookUpId"
   combobox.DataBindings.Add("SelectedValue", MyMainTable, "RefToLookUpTable")

and the datatypes of the sources of the .ValueMember and the ref column in the main table are different.

2)  a control (again usually a combo or list box) besides being bound to a datasource as in the first three lines of the example above, has its .Text property bound on these lines

   combobox.DataBindings.Add("Text", MyMainTable, "Something")

Where the "Something" is either a datatype which does not translate to "Text" or contains a value which does not exist in the combobox's datasource.
 
3)  a new record's creation inserts programmatically into a databound control a value which is inconsistent with datatype of the datasource column to which it is bound.

An underlying problem here is that if a binding manager's .Position property is set to a record which is (in its view) "invalid", rather than reporting an error it seems simply to move to the nearest "valid" record it can find.  From your description, that looks to be what is happening here.  So, if that is indeed the situation, the question really is: why does the binding manager think that the new record it creates is "invalid"?

The only way I know of sorting this out unless any of the above rings any bells with you is heuristic.  That really means "by trial and error": break all the bindings and restore them one by one until the problem is reproduced.  I'm reluctant to suggest that except as a last resort because - whilst experience shows that these symptoms can have a data-binding cause - I have come across cases where that wasn't the cause.

So there is one other approach you might like to try if none of the above descriptions seems likely to apply in this case.  That is to create the new record in the datasource, rather than with the binding manager, and see if that gets over the problem.  To do this, replace this line

            bmFound.AddNew()

with

            Dim dr as DataRow = MyTable.AddNew()
            MyTable.Rows.Add(dr)
            bmFound.Position = bmFound.Count - 1

Roger        
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 16595283
What happens in you define a CurrencyManager, instead of a BindingManagerBase?\


Bob
0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16596979
Thankyou for your suggustion Sancler I am attempting to use your mytable.rows.add suggustion and I have found something very, VERY strange.  I have added the code you suggusted (of course with the changes to fit my data) and have been stepping through the code and when I come to the bmfound.position = bmfound.count - 1 the bmfound.position value DOSEN'T CHANGE!  I can't understand why this would happen I think that it must have something to do with the values that the bindingmanagerbase thinks it should have in it. Because if I tell it to go to bmfound.cound - 2 it will work.  Any suggustions here?
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16598339
It still looks like a binding problem.  You could try Bob's suggestion and declare a CurrencyManager, although my guess is it will behave the same.  It is, after all, just another manifestation of BindingManagerBase.

Apart from that, I think you will have to look at the bindings.  That "the controls are bound from the Data Bindings properties and I am not setting them programaticially" does not guarantee that they are OK.  I'm assuming, from the terminology, that you are on VB.NET 2003.  If so, you will find the code that sets the bindings in the "Windows Form Designer generated code" Region.  If you're on 2005, they'll be in the form's .Designer.vb file which you can open by ensuring "Show All Files" is clicked in Solution Explorer and double clicking on the file.  Can you please copy all lines from either source which mention binding and paste them into a post?  And if you have any code for any of the events of any of the controls that are data-bound - e.g. a combobox's .SelectedValueChanged - include that, too.

As I said earlier, trying to pinpoint this sort of problem at a distance is very difficult.  But if I can see those bits of code, I might spot something, or at least be able to give you a better idea of where to look.

Roger
0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16599845
The following is the databinding information from the Windows Form Designer Generated Code.  Something I realized that I haven't mentioned before.  I have a position_changed Sub that has code in it to fill out labels on this form reflecting related data from another table.  I will place that in a following post.



        'txtFName
        '
        Me.txtFName.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.DsFound1, "Person.First_Name"))
        'DsFound1
        '
        Me.DsFound1.DataSetName = "dsFound"
        Me.DsFound1.Locale = New System.Globalization.CultureInfo("en-US")
        'txtLName
        '
        Me.txtLName.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.DsFound1, "Person.Last_Name"))
        'txtMaiden
        '
        Me.txtMaiden.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.DsFound1, "Person.Maiden_Name"))
        'lblID
        '
        Me.lblID.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.DsFound1, "Person.Person_ID"))
        'cmbSex
        '
        Me.cmbSex.DataBindings.Add(New System.Windows.Forms.Binding("SelectedValue", Me.DsFound1, "Person.Gender"))
        Me.cmbSex.DataSource = Me.DsFound1.Sex
        Me.cmbSex.DisplayMember = "sexVal"
        Me.cmbSex.ValueMember = "sexID"
        'chkMarried
        '
        Me.chkMarried.DataBindings.Add(New System.Windows.Forms.Binding("Checked", Me.DsFound1, "Person.Married"))
        'chkMail
        '
        Me.chkMail.DataBindings.Add(New System.Windows.Forms.Binding("Checked", Me.DsFound1, "Person.Current_Mail"))
        'chkDead
        '
        Me.chkDead.DataBindings.Add(New System.Windows.Forms.Binding("Checked", Me.DsFound1, "Person.Deceased"))
        'chk100
        '
        Me.chk100.DataBindings.Add(New System.Windows.Forms.Binding("Checked", Me.DsFound1, "Person.Donations_100"))
        'chkPlaque
        '
        Me.chkPlaque.DataBindings.Add(New System.Windows.Forms.Binding("Checked", Me.DsFound1, "Person.Plaque"))
        'lblAdd
        '
        Me.lblAdd.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.DsFound1, "Person.Address_ID"))
0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16599871
This is the private sub that fires when the bindingmanagerbase bmFound.position has been changed.

    Private Sub Position_Changed(ByVal sender As Object, ByVal e As EventArgs)
        Dim dvrAddressView As New DataView

        With dvrAddressView
            .Table = DsFound1.Address
            .RowFilter = "Address_ID = '" & lblAdd.Text & "'"
        End With

        lblStAdd.Text = dvrAddressView.Item(0).Item("Street_Add")
        Try
            lblStAdd2.Text = dvrAddressView.Item(0).Item("Add_Line")
        Catch ex As Exception
            lblStAdd2.Text = "<none>"
        End Try
        lblCity.Text = dvrAddressView.Item(0).Item("City")
        lblZip.Text = dvrAddressView.Item(0).Item("ZIP")
        cmbState.SelectedValue = dvrAddressView.Item(0).Item("State")

        With bmFound
            sbpRecordNumber.Text = "Record " & (.Position + 1).ToString & " of " & (.Count.ToString())
            If DsFound1.Tables.Item("Person").Rows.Item(.Position).IsNull("Married_ID") Then
                chkAlum.Checked = False
                lblMName.Text = ""
            Else
                Dim strMarried_ID As String
                Dim strMName As String
                chkAlum.Checked = True
                strMarried_ID = DsFound1.Tables.Item("person").Rows.Item(.Position).Item("Married_ID")
                strMName = DsFound1.Tables.Item("person").Rows.Find(strMarried_ID).Item("First_Name")
                strMName = strMName & " " & DsFound1.Tables.Item("person").Rows.Find(strMarried_ID).Item("Last_Name")
                lblMName.Text = strMName
            End If
        End With
    End Sub
0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16600161
The problem has appeared to have mutated slightly due to the changes that I have made as per Sancler's suggustion.  Here is what I have done:

1.  I have made the change to use the MyTable.Rows.Add(dr)
2.  I am filling the row with some dummy data and that *HAS* corrected the problem of not editing the new record!
3.  After adding the new row with dummy data I execute the

The mutation however is now this,  I am able to see the new record in the form and then make changes but when I execue the bmfound.endcurrentedit followed by the daPerson.update command it is telling me that 0 records are affected and I checked the dsfound1.haschanges is false.  This is happening even though I am making changes to the record in the form.


Below is the code for my btnAdd and btnEnd click events

    Private Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
        If btnAdd.Text = "Add Person" Then
            unlockBoxes()
            disableNav()
            setButtonForEdit()
            bmFound.EndCurrentEdit()

            Dim myTable As DataTable
            myTable = DsFound1.Tables("Person")
            ' Declare an object variable.
            Dim objMax As Object
            objMax = myTable.Compute("MAX(Person_ID)", "") + 1

            Dim dr As DataRow = DsFound1.Tables.Item("Person").NewRow
            dr.Item("Last_Name") = "Last Name"
            dr.Item("First_Name") = "First Name"
            dr.Item("Gender") = 2
            dr.Item("Married") = 0
            dr.Item("Maiden_Name") = ""
            dr.Item("Address_ID") = 0
            dr.Item("Current_Mail") = 1
            dr.Item("Plaque") = 0
            dr.Item("Donations_100") = 0
            dr.Item("Deceased") = 0

            Try
                DsFound1.Tables.Item("Person").Rows.Add(dr)
                daPerson.Update(DsFound1)
                DsFound1.AcceptChanges()
            Catch ex As Exception
                MessageBox.Show(ex.Message, "Sorry An Error Occoured")
            End Try

            bmFound.Position = bmFound.Count - 1
            'Position_Changed(sender, e)

            'lblID.Text = objMax
            'clearFields()
        End If
    End Sub

    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        If DsFound1.HasChanges Then
            Try

                bmFound.EndCurrentEdit()
                daPerson.Update(DsFound1)
                DsFound1.AcceptChanges()
                lockBoxes()
                enableNav()
                resetButtonsAfterEdit()

            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If
    End Sub
0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16600183
I also am showing no changes if I do an edit of an existing record and try to save it.
0
 
LVL 34

Expert Comment

by:Sancler
ID: 16601465
The mutated problem with the revised code is here

    Private Sub btnEnd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEnd.Click
        If DsFound1.HasChanges Then
            Try

                bmFound.EndCurrentEdit() '<<< THIS LINE SHOULD GO BEFORE THE HasChanges CHECK
                daPerson.Update(DsFound1)
                DsFound1.AcceptChanges()
                lockBoxes()
                enableNav()
                resetButtonsAfterEdit()

            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        End If
    End Sub

When a user is editing a record in bound controls those changes are not actually "committed" to the source datatable until that "edit" is ended.  This can happen automatically, if the user navigates to a new record.  Otherwise, it has to be called explicitly: which I think is the case here.  When it is called, it puts the changes into the datatable and sets the rowstate flags in the changed datarow.  The .HasChanges test reports the result of looking at those flags.  If you call .HasChanges before .EndCurrentEdit, the flags have not yet been set, so it says there are no changes.  Make it

        bmFound.EndCurrentEdit()
        If DsFound1.HasChanges Then 'etc

Apart from that, it looks OK to me.  But if the above doesn't sort out the problem, can I please see the code by which you declare bmFound?

And although I doubt that this is a factor in the problem, can you confirm the datatype of the Address_ID field in the Address table?  I ask because you treat it as a string (by putting single quotes around it) in this line in the Position_Changed sub

            .RowFilter = "Address_ID = '" & lblAdd.Text & "'"

Indeed it is, in lblAdd.Text, a string.  But it appears to derive from a number.  lblAdd.Text was filled (in the btnAdd_Click sub, although the line is commented out in your posting) from objMax and that appears be the result of a numerical calculation

            objMax = myTable.Compute("MAX(Person_ID)", "") + 1

As, so far as I can see, the labels mentioned in the Position_Changed sub are not bound, a string Foreign Key in the Address table purportedly matching a numeric Primary Key in the Person table should not cause binding problems.  But it still looked a bit odd to me.

I'm in the UK, and off to bed now.  But I'll check in again in the morning.

Roger

0
 
LVL 2

Author Comment

by:Bull_81073
ID: 16605894
Sancler you are a saint!  I don't know how long I would have been working on this without you.

Placing the endcurrentedit did fix the update problem and you are right about the .rowFilter statement in my Position_Changed sub.  It is a number but because I am not enforcing strict rules it was automaticially being converted between a number and a string.  I will tell you though that the Address_ID label is not what was being set by the objMax it was the Person_ID label, because I am displaying info from two tables on this form.  One that they can edit here and one they have to click on an edit button in order to alter.

Also as you noticed the objMax lines are commented out.  This is because I was using them to generate the next step in the primary key values but discovered that VB was doing that automatically when we do the table add method.  It supprises me because I am using an access DB and was under the impression that key generation was a DBMS function.  Anyway thanks for the help!
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

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

This article explains how to create and use a custom WaterMark textbox class.  The custom WaterMark textbox class allows you to set the WaterMark Background Color and WaterMark text at design time.   IMAGE OF WATERMARKS STEPS Create VB …
Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
Loops Section Overview
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses
Course of the Month20 days, 9 hours left to enroll

868 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