locked
Negate Or Avoid "TextChanged" Event RRS feed

  • Question

  • When controls are filled from a database being loaded, the Text Changed event is triggered.

    I want to  signal the User that a change has been made and not to forget to save their work. The ideal situation would be to fire the warning message from the Text Changed...but this event fires when the record is loaded from the database which would trigger a false signal.

    The ideal situation would be a way to abort the Text Changed event if it was created from a database source filling a form. Is there a way to abort the Text Changed event with an "if source is database" statement?  If there is, I can't find it

    Does anyone have any suggestions?

    Milt


    sirmilt

    Thursday, September 5, 2013 5:53 PM

Answers

  • On FormLoad() or however you are loading with code to the control on firsttime, you set a global Boolean flag to true indicating you in a firsttime load condition.

    In the Textchanged event as the first code of the event,  it should check the Boolean flag to be true. If it is true, then you exit immediately out of the event and do nothing. If flag is not true, then you know it is not in a firsttime load situation,  and the user has changed data in the control that raised the event.

    During the firsttime load of controls at the top of this code procedure,  you set the flag to true. And at the end of this code, you set the flag to false.

    It's a known common coding procedure to handle the control's changed event in loading data to the control in a firsttime load situation. 

     
    • Marked as answer by sirMilt Thursday, September 5, 2013 7:34 PM
    Thursday, September 5, 2013 6:37 PM
  • @sirmilt

    The simple technique you are using and I have used over the years was shown to me back in 1996 or something with VB3. It works and I use it all the time when dealing with a control's Changed event when loading data to the controls on firsttime load with VB and C# applications.  

    It doesn't need to get anymore complicated than that. :)

    • Marked as answer by sirMilt Friday, September 6, 2013 1:13 PM
    Thursday, September 5, 2013 10:54 PM

All replies

  • I'm guessing you're talking about a TableAdapter's .Fill method?

    If so and if it's only done once - in the form's .Load event - then remove the handlers of everything as the first lines in the .Load event and then in the form's .Shown event, add them back.

    That's one way - but it'll only work for that first time.

    Another way - the way I've come to do it - is that I have a class-scoped boolean that I call "dbIsChanging" and I set it to true. In the form's .Shown event I set it to false, but also anytime that I call the .Fill, just beforehand I set it to true then afterward set it to false.

    Then in any event which will be affected, I have it first check for the state of that boolean:

    If Not dbIsUpdating Then
    ' .....
    End If


    Please call me Frank :)

    Thursday, September 5, 2013 6:01 PM
  • On FormLoad() or however you are loading with code to the control on firsttime, you set a global Boolean flag to true indicating you in a firsttime load condition.

    In the Textchanged event as the first code of the event,  it should check the Boolean flag to be true. If it is true, then you exit immediately out of the event and do nothing. If flag is not true, then you know it is not in a firsttime load situation,  and the user has changed data in the control that raised the event.

    During the firsttime load of controls at the top of this code procedure,  you set the flag to true. And at the end of this code, you set the flag to false.

    It's a known common coding procedure to handle the control's changed event in loading data to the control in a firsttime load situation. 

     
    • Marked as answer by sirMilt Thursday, September 5, 2013 7:34 PM
    Thursday, September 5, 2013 6:37 PM
  • Thanks for the very quick reply, darnold924:

    I thought of this not long after I posted my question but wasn't sure about how I was going to turn the flag to false and at the end of the Load procedure as you suggested is perfect, thanks again for your suggestion.

    Milt


    sirmilt

    Thursday, September 5, 2013 7:40 PM
  • Thanks for the very quick reply, darnold924:

    I thought of this not long after I posted my question but wasn't sure about how I was going to turn the flag to false and at the end of the Load procedure as you suggested is perfect, thanks again for your suggestion.

    Milt


    sirmilt


    ...the same thing that I said ...

    Please call me Frank :)

    Thursday, September 5, 2013 7:41 PM
  • @Frank

    <copied>

    ...the same thing that I said ...

    <end>

    Well Frank, you need to keep it simple in layman terms. "Handler" no man it's not what people are looking for when they seek help in looking for an explanation or how to. They want it broken down so that they understand what you are talking about.  :)

    Thursday, September 5, 2013 7:52 PM
  • @Frank

    <copied>

    ...the same thing that I said ...

    <end>

    Well Frank, you need to keep it simple in layman terms. "Handler" no man it's not what people are looking for when they seek help in looking for an explanation or how to. They want it broken down so that they understand what you are talking about.  :)

    I was saying that's one way - and then said it's NOT the way I do it.

    That doesn't mean that the way I do it - the same way you suggested also - is the ONLY way. I wanted to explain that there are options.

    I disagree with anything being called "global" so I don't use that term; I said "class-scoped" which [should have been] understood but if not, then - so be it. But there is no such thing as a "global" variable in my opinion. It's the scope of the variable that's at heart.

    At any rate, he has his answer ... so that's a good thing.


    Please call me Frank :)

    Thursday, September 5, 2013 7:56 PM
  • @Frank

    I know what you mean by class-scope. I read the cert books, took and past the tests. But that doesn't mean some else knows what you are talking about. They do understand the word "global". And again, you have to keep explanations or how to(s) simple.  

    Thursday, September 5, 2013 8:06 PM
  • @Frank

    I know what you mean by class-scope. I read the cert books, took and past the tests. But that doesn't mean some else knows what you are talking about. They do understand the word "global". And again, you have to keep explanations or how to(s) simple.  

    I disagree with the "keep it simple stupid" entirely.

    Of course it depends on the audience, but this is, or at least theoretically, a group of developers.

    That said, I know what you mean. Some here would have no idea about scope, but -- shouldn't that bring up the dialogue then? Let them ask "what do you mean class-scoped" or "how is that different from block-scoped?" and particularly "why does it matter" (which might lead into a discussion about memory).

    That opens doors and opens eyes - many more people read than ever actually chime in.

    <groan>

    It's all a moot point, I suppose.

    Seriously though, I'm glad he got his answer (not said facetiously).

    :)


    Please call me Frank :)

    Thursday, September 5, 2013 8:14 PM
  • @Frank

    Well Frank what can I tell you.

    <copied>

    That said, I know what you mean. Some here would have no idea about scope, but -- shouldn't that bring up the dialogue then? Let them ask "what do you mean class-scoped" or "how is that different from block-scoped?" and particularly "why does it matter" (which might lead into a discussion about memory).

    <end>

    Look around Frank, most people are not looking to get into a discussion when they are looking for answers and solutions to problems in forms or NG(s). It's I need help, can you help me, give me the answer I am looking for, thank ya and thank ya very much -- bye.

    That's what it's about Frank. :)

     

    Thursday, September 5, 2013 8:28 PM
  • Look around Frank, most people are not looking to get into a discussion when they are looking for answers and solutions to problems in forms or NG(s). It's I need help, can you help me, give me the answer I am looking for, thank ya and thank ya very much -- bye.

    That's what it's about Frank. :)

    We'll agree to disagree then.


    Please call me Frank :)

    Thursday, September 5, 2013 8:30 PM
  • Have you ever faced users or clients Frank? If you have faced them, then you just know what to do, which is to break it down to them and move on. :) It applies to the forums and NG(s).

    bye

    Thursday, September 5, 2013 8:37 PM
  • This in my opinion:

    I think the Text_Changed event is a poor choice for determining if a user made a change to the data.  For one, this event fires with each keystroke.  Second, the user may have changed the data back to the original value. When the user exits, the "Do you want to Save the changes?" pops up when no changes are made. And that may confuse some users.

    When controls are filled from the database, I also set the Tag property of the control with the original value.  When the user exits, I compare the current value of the control with the controls Tag property, and if different then present the "Do you want to save changes?" message. 


    The difference between genius and stupidity is that genius has its limits.

    Thursday, September 5, 2013 8:49 PM
  • This in my opinion:

    I think the Text_Changed event is a poor choice for determining if a user made a change to the data.  For one, this event fires with each keystroke.  Second, the user may have changed the data back to the original value. When the user exits, the "Do you want to Save the changes?" pops up when no changes are made. And that may confuse some users.

    When controls are filled from the database, I also set the Tag property of the control with the original value.  When the user exits, I compare the current value of the control with the controls Tag property, and if different then present the "Do you want to save changes?" message.

    What do you think about the DataSet.GetChanges Method?


    Please call me Frank :)

    Thursday, September 5, 2013 9:06 PM
  • Frank,

    In this case, I am assuming the controls are filled from the dataset and the controls are not bound to the dataset, and the dataset would only be loaded with updates if the Update button was clicked.  So there would be no changes in the dataset until the Update process started.  Now if a datatable was the datasource of a datagridview, I would check the dataset's HasChanges property to determine if the "Do you want to save changes?" should be displayed.

    The only time I use DataSet.GetChanges method is if I want to control the order of updating the database.  For example, do deletes, then updates, then inserts.


    The difference between genius and stupidity is that genius has its limits.

    Thursday, September 5, 2013 9:23 PM
  • Frank,

    In this case, I am assuming the controls are filled from the dataset and the controls are not bound to the dataset, and the dataset would only be loaded with updates if the Update button was clicked.  So there would be no changes in the dataset until the Update process started.  Now if a datatable was the datasource of a datagridview, I would check the dataset's HasChanges property to determine if the "Do you want to save changes?" should be displayed.

    The only time I use DataSet.GetChanges method is if I want to control the order of updating the database.  For example, do deletes, then updates, then inserts.

    I'll be the first to say that I'm a database lightweight, but yes - I did assume that the controls were bound.

    Good information - thanks. :)


    Please call me Frank :)

    Thursday, September 5, 2013 9:26 PM
  • Frank, One other thing.  I wish the datatable had the HasChanges property, but it doesn't.  After all, the HasChanges property is set based on the rowstate which is in the datatable.  The dataset is a collection of datatables with relations properties.  And looking in the MSDN documentation that comes with VS 2008, HasChanges is not listed for a dataset.  However, it is in intellisense.

    The difference between genius and stupidity is that genius has its limits.

    Thursday, September 5, 2013 9:39 PM
  • Wow. I didn't expect all of these differences to come into play.

    Following darnold924's suggestion In the form load I added the Boolean =True immediately after the form load I added the Boolean=False.

    In the Text Changed I checked for a True value and if False and the reminder routine that I wanted...it worked perfectly. 

    As I said earlier, darnold924's suggestion  was not only simple, it did the job anything I excess would have been a waste of time.

    Milt


    sirmilt

    Thursday, September 5, 2013 9:53 PM
  • sirmilt, I used darnold's method back in 2003.  Then users called and said why is it asking me if I want to save changes when I didn't change anything.

    I always use a class level Boolean to indicate if the form's load event is executing.  When you set the combobox's DataSource, DisplayMember and ValueMember properties, the combobox's SelectedIndexChanged (or SelectedValueChanged) fires 3 times. Or in the textbox's text changed event if I am appending a "-" when the textlength is 3 or 7 when entering a phone number for example. 


    The difference between genius and stupidity is that genius has its limits.

    Thursday, September 5, 2013 10:02 PM
  • @sirmilt

    The simple technique you are using and I have used over the years was shown to me back in 1996 or something with VB3. It works and I use it all the time when dealing with a control's Changed event when loading data to the controls on firsttime load with VB and C# applications.  

    It doesn't need to get anymore complicated than that. :)

    • Marked as answer by sirMilt Friday, September 6, 2013 1:13 PM
    Thursday, September 5, 2013 10:54 PM
  • @darnold924,

    Why not just set the Changed Boolean variable to true in the form's keypress event.  It will give you the same result as you recommend.


    The difference between genius and stupidity is that genius has its limits.

    Friday, September 6, 2013 2:15 PM
  • @Frank

    Well Frank what can I tell you.

    <copied>

    That said, I know what you mean. Some here would have no idea about scope, but -- shouldn't that bring up the dialogue then? Let them ask "what do you mean class-scoped" or "how is that different from block-scoped?" and particularly "why does it matter" (which might lead into a discussion about memory).

    <end>

    Look around Frank, most people are not looking to get into a discussion when they are looking for answers and solutions to problems in forms or NG(s). It's I need help, can you help me, give me the answer I am looking for, thank ya and thank ya very much -- bye.

    That's what it's about Frank. :)

     

    You are correct, a lot of people just want an answer or solution.  The process of helping them doesn't preclude discussion, and certainly should not use terminology that is not clear.  Your usage of global and assertion that everyone knows what that means is troublesome, especially for new people. I am guessing that this is what you proposed:

    Public Class Form2
        Dim aGlobalThatIsNotGlobal As Boolean
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            aGlobalThatIsNotGlobal = True
        End Sub
    End Class

    So what happens when SirMilt creates a new form etc. and wants to access that "global" variable?  The answer is they come back and ask another question.  If we had followed Frank's advice, and used clear terminology, that might of caused further discussion, SirMilt would have learned MORE than the answer to the question, they might have learned concepts that would have precluded the need for other questions.

    Module globalVar
        Public aGlobalVar As Boolean
    End Module
    
    Public Class Form2
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            aGlobalVar = True
        End Sub
    End Class
    
    Public Class Form3
    
        Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            aGlobalVar = True
        End Sub
    End Class


    "Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein

    Friday, September 6, 2013 3:08 PM
  • <copied>

    @darnold924,

    Why not just set the Changed Boolean variable to true in the form's keypress event.  It will give you the same result as you recommend.

    <end>

    The keypress event was not the issue. The keypress event was not the event that was firing upon firsttime load of data to the control. It was the Changed event that was firing.

    Friday, September 6, 2013 4:31 PM
  • @Multics

    <copied>

    So what happens when SirMilt creates a new form etc. and wants to access that "global" variable

    <end>

    I thought Module was global to all things VB in a solution, particularly from forms in the same project that can see things on Module. I don't see your point.

    May I ask why you are trying to make this more complicated than it needs to be?

    Friday, September 6, 2013 4:38 PM
  • @Multics

    <copied>

    So what happens when SirMilt creates a new form etc. and wants to access that "global" variable

    <end>

    I thought Module was global to all things VB in a solution, particularly from forms in the same project that can see things on Module. I don't see your point.

    May I ask why you are trying to make this more complicated than it needs to be?

    It depends on how and where  things are declared.  That was the point Frank was making.  Having a user declare a variable within a form (class / module scope) does not make it 'global'.  So yes you satisfied this:

    "...most people are not looking to get into a discussion when they are looking for answers and solutions to problems in forms or NG(s). It's I need help, can you help me, give me the answer I am looking for..."

    but you may have left SirMilt with the impression that the variable WAS global.  If all SirMilt does is have one form with one class scoped variable there isn't an issue with their problem, but the variable is NOT global, and if they think so then you have done them a disservice.

    Module globalvars
        Dim thisIsNot As Boolean 'this is not global, local to module globalvars
        Public thisIs As Boolean 'this is global
        Private Sub foo()
            'thisIsNotf2 = True 'compile error
        End Sub
    End Module
    
    Public Class Form2
    
        'this is what you proposed as 'global'
        Dim thisIsNotf2 As Boolean 'this is not global, local to form2
    
        Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            thisIs = True
        End Sub
    End Class
    Scope Doc


    "Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein


    • Edited by dbasnett Friday, September 6, 2013 5:59 PM
    Friday, September 6, 2013 5:57 PM
  • <copied>

    @darnold924,

    Why not just set the Changed Boolean variable to true in the form's keypress event.  It will give you the same result as you recommend.

    <end>

    The keypress event was not the issue. The keypress event was not the event that was firing upon firsttime load of data to the control. It was the Changed event that was firing.


         The issue was determining whether the user changed any data.  The OP was using the Text_Changed event to set a Boolean variable, but when loading data to the control, this event fires. My point is after using the form loading indicator, the Text_changed event cannot determine if the data was changed, only that the text changed. The user could have entered a value, then pressed backspace, then entered the original value.  Even though the data didn't change the Dirty Boolean is true.

    The difference between genius and stupidity is that genius has its limits.

    Friday, September 6, 2013 6:05 PM
  • @Multics

    You are hurting my head with this constant complications of yours. The OP got what he wanted, it fixed his problem, and you should just let it go.

    Friday, September 6, 2013 6:58 PM
  • The OP got what he wanted, it fixed his problem, and you should just let it go.

    I agree.

    This thread has now concluded. :)


    Please call me Frank :)

    Friday, September 6, 2013 7:08 PM