Dataset?/CurrencyManager?/ScrollBar? affected improperly after using RowFilter

This is a continuation of a previous posting that now deals with a scrollbar inconsistency.  My other posting was resolved.

I have pasted three routines at the bottom for your review.  The first one is when a data entry form loads with an existing record.
The second is when I click on a button to clear my form.  The third one is if I use a scrollbar on that form.  The scrollbar is
minimized in size where only the scroll up and scroll down arrows are visible.  The user clicks each time to move the scrollbar value.

All textboxes and combo boxes are bound by a dataview.
I am also using CurrencyManager with the same dataview to facilitate the movement up and down from clicking my scrollbar.

Step 1 -
If I load a form and display an existing record by passing a value to a combo box as show in my first piece of code, the form populates
properly and I can use the scrollbar without fail.  Back and forth, back and form....no problem.

Step 2 -
When I click on the Clear/New button with the code below it seems to work properly.  RowFilter being set to "contact_id = 0"
means that the dataset will return empty.  There is no record with a contact_id = 0.  This way I am able to re-initialize my text
boxes and combo boxes to empty.

Step 3 -
If I have previously click on the Clear/New button (having an empty form), decide that I don't want to add a new record, and click on
the scroll bar to re-display the first record in the dataview....everything goes haywire.  It's as if my dataview is getting trashed.  It actually
may even be affecting things down to my dataset.

The first row in the dataset loses values in various fields.  One of my combo boxes will not display a value at all until I actually click on it
and chose an existing value....then I can click on the scrollbar and it populates properly.....but if I back up with the scrollbar it still will not
display the value on the first record.

Step 4 -
THEN, if I click on the scrollbar again, it goes into outer space as if it doesn't know what to do.  The only way to get out is to end is to
click on 'Stop Debug' button.



QUESTIONS -
Does there appear to be something I'm missing in my code or not doing this the most appropriate way?

Is there something I need to be refreshing after resetting the rowfilter = "".  Or is there a different way
to clear my form of data than 'contact_id = 0'...which is not a valid contact_id so that this thing doesn't
go crazy?

When I debug my VScrollBar1_Scroll and click on the scrollbar, it actually flows through the .Scroll twice.  The first time
the Scroll.Value = to the original value and the second time around with the value + 1.  Is this normal?

Thanks for any help you can give.

Phil


    Private Sub ContactMgmt_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        BuildTablesAndViews()
        BuildComboBoxes()
        BindControls()
        If glNewRec = False Then
            Try
                cmboIndex.SelectedValue = glRecID
                RecIDIndex = cmboIndex.SelectedIndex
                VScrollBar1.Value = cmboIndex.SelectedIndex
            Catch ex As Exception
                MsgBox(ex.Message, MsgBoxStyle.OKOnly Or MsgBoxStyle.Critical, Me.Text)
            Finally
            End Try
            dvPropertiesOwned.RowFilter = "owner_id = " & txtContactID.Text
        Else
            cmdClearNew_Click(Nothing, Nothing)
        End If
        VScrollBar1.Maximum = dvContact.Count
    End Sub

    Private Sub cmdClearNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdClearNew.Click
        glNewRec = True
        RecIDIndex = 0
        VScrollBar1.Value = 0
        dvContact.RowFilter = "contact_id = 0"      '<---- no record exists with contact_id = 0
        dvPropertiesOwned.RowFilter = "owner_id = 0"      '<---- no record exists with owner_id = 0
        cmboContactType.Focus()
    End Sub

    Private Sub VScrollBar1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles VScrollBar1.Scroll
        Select Case VScrollBar1.Value
            Case Is > RecIDIndex        ' MOVING FORWARD
                If glNewRec = True Then
                    glNewRec = False
                    dvContact.RowFilter = ""              <----- I've even tried to set it as "contact_id <> 0"
                    cmContact.Position = 0
                    RecIDIndex = 0
                    VScrollBar1.Value = 0
                Else
                    RecIDIndex = VScrollBar1.Value
                    cmContact.Position += 1
                End If
            Case Is < RecIDIndex        ' MOVING BACKWARD
                If glNewRec = True Then
                    glNewRec = False
                    cmContact.Position = 0
                    RecIDIndex = 0
                    VScrollBar1.Value = 0
                Else
                    If VScrollBar1.Value <> -1 Then
                        RecIDIndex = VScrollBar1.Value
                        cmContact.Position -= 1
                    Else
                        RecIDIndex = 0
                        VScrollBar1.Value = 0
                        cmContact.Position = 0
                    End If
                End If
        End Select
        If txtContactID.Text <> "" Then
            dvPropertiesOwned.RowFilter = "owner_id = " & txtContactID.Text
        End If
    End Sub


TSFLLCAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SanclerCommented:
Phil

I have, based on the code (and discussion) in your other question, tried replacing your vscrollbar with two buttons.  Here's the code.

From the "Designer" Region

    Friend WithEvents btnUp As System.Windows.Forms.Button
    Friend WithEvents btnDown As System.Windows.Forms.Button

...

        Me.btnDown = New System.Windows.Forms.Button
        Me.btnUp = New System.Windows.Forms.Button

...

        Me.GroupBox1.Controls.Add(Me.btnDown)
        Me.GroupBox1.Controls.Add(Me.btnUp)

...

        'btnDown
        '
        Me.btnDown.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.btnDown.Image = CType(resources.GetObject("btnDown.Image"), System.Drawing.Image)
        Me.btnDown.ImageAlign = System.Drawing.ContentAlignment.BottomCenter
        Me.btnDown.Location = New System.Drawing.Point(455, 30)
        Me.btnDown.Name = "btnDown"
        Me.btnDown.Size = New System.Drawing.Size(24, 10)
        Me.btnDown.TabIndex = 223
        '
        'btnUp
        '
        Me.btnUp.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.btnUp.Image = CType(resources.GetObject("btnUp.Image"), System.Drawing.Image)
        Me.btnUp.ImageAlign = System.Drawing.ContentAlignment.BottomCenter
        Me.btnUp.Location = New System.Drawing.Point(455, 20)
        Me.btnUp.Name = "btnUp"
        Me.btnUp.Size = New System.Drawing.Size(24, 10)
        Me.btnUp.TabIndex = 222

You won't have the "btnUp.Image" and "btnDown.Image" but they are just simple 6 pixel by 4 pixel bitmaps of arrowheads.  The sizes and locations place these buttons precisely where (on the code posted in your other question) your vscrollbar appeared.

The operating code is simply

    Private Sub btnUp_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnUp.Click
        cmContact.Position -= 1
    End Sub

    Private Sub btnDown_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDown.Click
        cmContact.Position += 1
    End Sub

It's your call, but I think this meets your GUI needs avoiding any complications of vscrollbar coding.  

I think (hope) my additional comments on your other question deal with the other points in this posting.

Roger
0
TSFLLCAuthor Commented:
Roger,

Yes, you have gone above and beyond for 250 points from the other posting.  You don't know now much  you
helped with 4-5 issues altogether.  We'll close that one for good.

I was able to resolve all my issues with my scrollbar last night.  Just the same, I will test this code because it
will definitely reduce the confusion with my scroll routine.

I also appreciate your input regarding ManagerBase/CurrencyManager.  I have come to a point where I am
binding ONLY one field to the same dataview as is being used with the CurrencyManager.

It may be improper (I'm unsure at this point) but I'm populating my form like this:

        Dim dr As DataRow = dtContact.Rows(CurrRowIndex)
        txtContactID.Text = dr.Item("contact_id").ToString()
        cmboContactName.SelectedValue = dr.Item("contact_id").ToString()
        cmboContactType.SelectedValue = dr.Item("contact_type_id").ToString()
        cmboMrMrs.SelectedValue = dr.Item("salutation_id").ToString()
        txtFirstName.Text = dr.Item("first_name").ToString()
        txtInitial.Text = dr.Item("initial").ToString()
        txtLastName.Text = dr.Item("last_name").ToString()
        Add fields to follow....

All of the combo boxes have datasources different from the CurrencyManager.

When I want to clear the form I just add a new row (as you recommended) and
set text = "" or selectedvalue = 0.

If the user decides to click on the scroll bar without doing anything with the
new row:

        Dim dr As DataRow = dtContact.Rows(dvContact.Count - 1)
        dr.Delete()

Everything, I mean EVERYTHING, is working the way I want it to except for one
thing.  This is my last flow problem:

1)  The user has an existing record on form.
2)  The user clicks the 'New Record' button (a row is added as said above).
3)  S/He decides not to add a record.
4)  Clicks the combo box (right beside the scrollbar) to pull up an existing record.

I can't get the combo box to remain on the index of the record chosen.  It
reverts back to the displayed record prior to clearing the form and adding the
empty row.  Only the combo box.  All other fields are fine.

I've identified that it is deals with deleting the empty row from #2.  I've verified
this because if I comment the dr.Delete() from the code below...the combo box
does not change improperly.

This is the code:
            If glNewRec = True Then
                Dim dr As DataRow = dtContact.Rows(dvContact.Count - 1)
                dr.Delete()
                PopulateFields(cmboIndex.SelectedIndex)
                cmContact.Position = cmboIndex.SelectedIndex
                RecIDIndex = cmboIndex.SelectedIndex
                VScrollBar1.Value = cmboIndex.SelectedIndex
                cmdClearNew.Enabled = True
                glNewRec = False
            Else
                If cmboIndex.SelectedIndex >= 0 Then
                    PopulateFields(cmboIndex.SelectedIndex)
               EndIf
           Endif

The combo box is initialized like this:

        dtContact = GetContact().Tables("contact")
        dvContact = dtContact.DefaultView
        dvsContact = dsContact.Tables("contact").DefaultView.DataViewManager.CreateDataView(dsContact.Tables("contact"))
        With cmboIndex
            .DataSource = dvsContact
            .ValueMember = "contact_id"
            .DisplayMember = "contact_index"
        End With


What gives?  Why does the delete of of the last row in the datatable affect my selectedindex of a combo box?

If I can get this resolved, I can incorporate all of this into my other 15-18 forms and be 80% done with this app.

Also, you made reference to capturing the problem of selectedindexchanged when the form is loading so that
you can exit sub.  You wrote something like  'if loading exit sub'.  I know you were paraphrasing but could you
write out the line of code.  I look for an hour and couldn't find what to do.  Hate to be a pain.  My brain is bruised
with everything I've learned in the last 4-5 days.

Thanks!

Phil
0
SanclerCommented:
Phil

Last point first.  I mistyped.  I should have typed

     If Loading Then Exit Sub 'I missed the THEN out: it's a normal conditional statement, on one line

So - at start of form

    Private Loading As Boolean = True

When all loading is done (probably at end of Form Load Sub)

   Loading = False

And in (for example)

    Private Sub cmboIndex_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmboIndex.SelectedIndexChanged

      If Loading Then Exit Sub
      'the code I want to deal with the event other than when it fires as the combo is being filled/bound

    End Sub

On the other issue, I need to cogitate.  I'll come back - but it may not be for a few hours.

Roger
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

TSFLLCAuthor Commented:
Roger,

Didn't realize you were talking about a created variable.   Duh!

Thought there was something inherant to VB while form was loading that could be referenced.

Thanks.

Phil
0
SanclerCommented:
Phil

I'm rather confused.  The design seems to have changed fairly drastically.  So I'm stabbing rather in the dark.  From your description of the remaining problem it still sounds to me like it MAY be a data-binding issue but

1) I'm not sure what is bound to what.  The way you are populating the textboxes makes me wonder whether they are now bound at all.

2) You say that "All of the combo boxes have datasources different from the CurrencyManager" but I assume from this snippet

                cmContact.Position = cmboIndex.SelectedIndex
                RecIDIndex = cmboIndex.SelectedIndex
                VScrollBar1.Value = cmboIndex.SelectedIndex
 
that cmContact is still the currency manager for the datasource that cmboIndex is bound to.

3) Every datasource actually has a "currency manager" that will manipulate (and be manipulated by) controls which are bound to that datasource whether a CurrencyManager is made explicit or not.  If an app wants a user to be able to navigate through records with "next/previous" buttons then it is necessary to make the CurrencyManager explicit so that it can code things like

    cm.Position +=1

But, even if it's not made explicit, it's there "in the background".  So just that other comboboxes "have datasources different from the CurrencyManager" does not necessarily mean that there might not be some binding conflict which is producing the symptoms.

On the other hand, there do seem to be some other quirks (or at least uncertainties) in the code that you show.

4) You say "I just add a new row (as you recommended)" but it looks, from this code

            If glNewRec = True Then
                Dim dr As DataRow = dtContact.Rows(dvContact.Count - 1)
                dr.Delete()

as though the new row that you have added must have been added to the datatable not - as I suggested - to the dataview.

5) Or if it was added to the dataview, but no .EndCurrentEdit has yet been called, the code just quoted will be deleting (or at least trying to delete) a row different from the new one.

6) Similarly if the new row was created with dtContact.NewRow but there has been no dtContact.Rows.Add(new row).

7) But even if all's OK so far, you are referencing a row in the dataTABLE by a .Count reference from the dataVIEW.  That may in practice, provided the dataview is not filtered at all, amount to the same thing.  But there can obviously (in theory) be situations in which it would not be OK and - just as matter of coding practice - it made me wince ;-)

What it all boils down to is, I'm afraid, I don't know - at the moment, anyway.

If you can answer some of the (implied) questions above I might be able to give it a better stab.

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

Roger
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
TSFLLCAuthor Commented:
Roger,

1)  You are correct.  I only have one field that is databound.  Otherwise I am populating all fields manually.

2)  All of my combo boxes have datasources other than the main datasource "contacts".

    Sub BuildComboBoxes()
        With cmboX
            .DataSource = dvContact
            .ValueMember = "contact_id"
            .DisplayMember = "contact_index"
        End With
        With cmboIndex
            .DataSource = dvsContact
            .ValueMember = "contact_id"
            .DisplayMember = "contact_index"
        End With
        With cmboContactType
            .DataSource = dtContactType
            .ValueMember = "field_order"
            .DisplayMember = "field_description"
        End With
        With cmboAssessmentCategory
            .DataSource = dtAssessmentCategory
            .ValueMember = "assessment_category_id"
            .DisplayMember = "assessment_category_description"
        End With
        With cmboPaymentTerms
            .DataSource = dtPaymentTerm
            .ValueMember = "payment_term_id"
            .DisplayMember = "payment_term_description"
        End With
    End Sub

    Private Sub BindControls()
        cmboX.DataBindings.Add("SelectedValue", dvContact, "contact_id")
        cmMainTable = CType(Me.BindingContext(dvContact), CurrencyManager)
    End Sub

3)  I saved the text I typed out yesterday afternoon in a text file and did not send it to you because I wanted to take a break.  Last night I decided to get back on my
problem.  

Quote- Every datasource actually has a "currency manager" that will manipulate (and be manipulated by) controls which are bound to that datasource whether a CurrencyManager is made explicit or not.

I believe what you said makes the greatest amount of sense to me now...after what I did last night.  The cmboIndex box was only being used as a 'lookup' box.
It had no bearing on anything else in the form.  Therefore, because it was originally bound to the same CurrencyManager/dataview as all of the other fields on the form and even after removing the databinding, it was still tied to the same table only through another view.  Modify something (add a row) in one dataview, it affects any other dataview associated with that table.

I resolved the problem COMPLETELY by making a clone of the dataset and using it with the cmboIndex combo box.  I'm assuming now that all I have to do is keep
the true dataset and the cloned dataset in synch ( add, delete, edit the Contact Name specifically in the clone) and it will work.

4-7)  It took forever for the code structure of adding/editing/deleting a row using the dataviewrow to sink in.  I did modify my code from adding to the table to adding it to the dataview.  Thanks for that info.

I'm sure that some of my problem deals with a lack of understanding of the tools available to me.  But through our conversations over the last few days a number of things have enlightened me.

I appreciate all of your help.

Phil



0
SanclerCommented:
Phil

Glad you got there in the end, and that I was able to help with it.

Roger
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.