Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
I have a simple data form that has various controls on it bound to data in a sql server database using all the visual tools such as dataset, tableadapters, and binding source.
 
Example firstname textbox, lastname textbox, date textbox (though on my form there are many more)
 
I need to determine if any data in any of those controls was modified so I can ask the user if they want to save before continuing, and enable the save button, things like that.
 
I can use the various events for each control such as validated, but I would have to do that for each control on the form, and it seems that would be something simpiler in say the binding source.
 
However, the bindingsource.currentchanged event fires whether or not anything was modified, and I have tried everything else I can think of.
 
I am thinking it shouldn't be that complicated.
 
Thanks in advance,
Posted 21-Sep-12 7:00am
Comments
Sergey Alexandrovich Kryukov at 21-Sep-12 13:07pm
   
To start with, you need to write down exact class name of the class you are working about. Fully-qualified, with its namespace, because many different classes in different libraries have the same simple name. Please use "Improve question" above.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Well, since you're working with a DataSet [^]it seems safe to assume you are actually binding to this and display a DataRow [^]on screen.
You could loop through the DataRows [^]in your DataSet and look at the RowState Property[^]. This returns a DataRowState Enumeration[^] value.
I think it's pretty obvious from there. Hope it helps Smile | :)
 
P.S. You're asking for an Event that triggers when anything changes. Obviously, when you use this method you don't need an Event anymore!
  Permalink  
v3
Comments
Joe Fager at 21-Sep-12 14:07pm
   
Yes, I understand this solution. However, I don't know when to check the RowState Property.
 
I want to check this before the user leaves the form or moves to another record. That way I can ask if they would like to save changes on that record before proceeding. So it would need to be an event such as BindingSource.CurrentChanged the problem with that is it happens after the user navigates to another row.
Naerling at 21-Sep-12 18:53pm
   
How about when the user clicks the 'Next' or 'Close' button (or FormClosing Event of the Form)? :)
Simply loop through the Rows of the DataTable until a DataRow.RowState returns anything else than Unchanged.
Joe Fager at 22-Sep-12 1:27am
   
That is probably what I will do. That makes it real easy because all I have to do is check the dataset for changes. dataset.haschanges and handle it from there. I made it a lot harder than it needed to be. I will be wanting to validate the controls individually anyway. As soon as the first validation event fires and passes I can enable the save button, and if they leave the form or the record, I can ask them to save changes.
Naerling at 22-Sep-12 3:47am
   
Actually I would not use the Validated Event at all. The only thing it allows you to do is trap the user in a Control (e.Cancel), it's the most annoying and user UNfriendly thing I've ever seen and used. Better is to look at the ErrorProvider Component (http://msdn.microsoft.com/en-us/library/system.windows.forms.errorprovider.aspx) and the IDataErrorInfo Interface (http://msdn.microsoft.com/en-us/library/system.componentmodel.idataerrorinfo.aspx). You can neatly do your validations in your business layer (where I think they belong) and clearly, but non-intrusively, show any errors to your users (without trapping them in a Control).
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Hi Friend,
I believe that you can use the method that I am gonna provide you here in VB too, since I am not working with VB and this one is in C#, so pretty off the language of your interest but perfect in the way what you require to do. I hope you will be able to translate it in VB since .NET is quite Language independent Smile | :)
 
Let us look at my solution, that I am giving you here after 1 hr of mind boggling work (only for you my friend)
 
See, the codes first, then I will explain it below :
The first thing is to define a global boolean
bool changed = false;
 
The next step is to define this inside Form Load Event:
foreach (Control mycon in this.Controls.OfType<TextBox>())
{
   mycon.TextChanged   +=  new EventHandler(mycon_TextChanged);
}
 
As you can see here, I simply looped through all the textbox controls (well you can do for other controls also) and added a single event handler function to all of them. Now let us see what's inside this function. so here's the code :
 
public void mycon_TextChanged(object sender, EventArgs e)
{
    changed = true;
    foreach(Control mycon in this.Controls.OfType<TextBox>())
    {
        mycon.TextChanged -= mycon_TextChanged;
    }
}
Now here I simply set that boolean to true and after that I removed all the event handlers since I guess they are no longer required as the close button now for sure will have to ask for saving the changes (Change has been made).
 
Now You simply need to test this boolean, and if it is set, implement your codes to save this new data Smile | :) Cheers
 
Regards
Tushar Srivastava Smile | :)
  Permalink  
v4
Comments
Joe Fager at 21-Sep-12 17:32pm
   
Thank you very much... I do think that this will work. I can't test it right now, but will not let your work go to waste. I will test it later. Thank you kindly. It makes sense to me and I can already see how it would work in VB.
Tushar Sriv at 21-Sep-12 17:37pm
   
Thank you sir, that you found it useful :-)
Naerling at 21-Sep-12 18:51pm
   
There's a few issues with this approach. First, it only works on TextBoxes, while I'm sure there might be some ComboBoxes, CheckBoxes, RadioButtons, etc. on an average form. Second, it won't work for Controls in any ContainerControls such as Panels, GroupBoxes, TabControls and SplitContainers. The latter is easily fixed by making your method a recursive one. The first isn't so easily fixed. You could use something like the Validated Event for each Control.
 
The following code fixes these issues (untested):
 
Private Sub AddValidatedHandlers(Byval c As Control)
If c IsNot Nothing Then
For Each ctrl As Control In c.Controls
AddValidatedHandlers(ctrl)
Next
AddHandler c.Validated, AddressOf Control_Validated
' Alternatively: AddHandler c.Validated, Sub (sender, e) changed = True
End If
End Sub
 
Now simply call the function as follows:
 
AddValidatedHandlers(Me)
 
My biggest problem with this approach, however, is that the moment values are changed 'in the background', or through some other means (for example a pop-up form) your logic is flawed. Only one Object knows if it has been changed or not, and that is the Object you're binding to. In this case the DataRow (which conveniently already tracks if it has been changed for you!). I really suggest you handle logic such as this in the 'business layer' rather than your UI layer.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 371
1 Sergey Alexandrovich Kryukov 286
2 RyanDev 75
3 PhilLenoir 70
4 Pheonyx 50
0 Sergey Alexandrovich Kryukov 6,676
1 OriginalGriff 6,056
2 CPallini 2,473
3 Richard MacCutchan 1,697
4 Abhinav S 1,560


Advertise | Privacy | Mobile
Web04 | 2.8.140821.2 | Last Updated 21 Sep 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100