Click here to Skip to main content
15,119,285 members
Articles / Desktop Programming / Windows Forms
Posted 12 Apr 2007


45 bookmarked

Dirty Button

Rate me:
Please Sign up or sign in to vote.
4.24/5 (19 votes)
30 Aug 2007CPOL4 min read
A button control that keeps track of the form’s dirty state.

Screenshot - dirtybutton.gif


When you do a project where the user has to fill in a lot of information, you often want to know if there has been changes made or not so that you can enable a Save button accordingly. Normally, you would put a Boolean variable in your code (e.g., bDirtyBit) and enter some code in each control's Change event (e.g., bDirtyBit=True or cmdSave.Enabled=True).

In the project I'm currently working on, I've got forms with hundreds of controls, and entering code into each control's Change event is very tiresome. Plus, it's very easy to miss a control when you add new controls. Also, it's a lot of unnecessary code that makes the really important code harder to read.

So, I decided to do a special button control that can handle all that automatically for me without any coding (actually, somebody else suggested the idea, but didn't know how to implement it). And, that's what I did. The button is very basic. It keeps track of all the important controls on your form, and enables the button if a change has been made. Thus, it keeps your code free of all the abovementioned, unnecessary code.

The project also demonstrates how you can use an Extender Provider to add properties to other controls. It is a lot easier than you would think...

This is my first submission to The Code Project, so I hope everything is OK. If you encounter any problems, please don't hesitate to contact me.

Using the code

The use of the control is extremely simple. Just drop it on your form and add this code to the Form_Load event:

Private Sub Form1_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load


End Sub

These basic controls are monitored for changes: CheckBox, ComboBox, DateTimePicker, MaskedTextBox, MonthCalendar, NumericUpDown, RadioButton, RichTextBox, TextBox, Button (optional).

**** New in Version 2.0 ****

  • The button adds a property to the monitorable controls called DirtyMonitored (similar to the way the Tooltip component adds a ToolTip property). If you have a single control of the type above on the form (or more than one) that you do not want to include in the monitoring process, simply set that property to False – and voila: it is omitted.
  • Please note: These properties are not really added to the controls themselves. They are actually a part of the DirtyButton. So, they're only visible at design time. That means that you cannot use code like this: TextBox17.DirtyMonitored=True at runtime. You can call DirtyButton.SetDirtyMonitored(Textbox17), but it will have no effect if you do it after calling the StartMonitoring method. In that case, you will probably have to call EndMonitoring and then StartMonitoring again, but I haven't tried it, so I'm not 100% certain it works.

    And, these controls are not monitored (because from what criteria/event would we enable the button?): Label, LinkLabel, ListBox, ListView, NotifyIcon, PictureBox, ProgressBar, ToolTip, TreeView, and WebBrowser.

    You can set the dirty state manually if the controls above are changed in a way that you consider relevant, using:


    There are a few other methods and properties that are good to know: ResetDirtyState, IsDirty, SuspendMonitoring, ResumeMonitoring, SetDirtyOnButtonClick etc. All of these are practically self-explanatory, very simple to use, and the use is shown in the demo project.

  • I "accidentally" noticed that there was a bug in my initial control. If you place the DirtyButton in a GroupBox, it is only the controls nested in that GroupBox that are monitored. Not the controls outside or in other GroupBoxes. That is because I used the Parent property to determine where the DirtyButton was located, not the FindForm method.
  • But then I thought: well, maybe somebody likes it that way, and wants to have two or more GroupBoxes each with their own DirtyButton. Other people might want the button to monitor the whole form even if it's in a GroupBox.

    So, instead of fixing the bug, I simply made it a property of the button: MonitoringScope, which can be set to WholeForm or ParentOnly. That solved that problem!

  • I added a DirtyStateChanged event for the DirtyButton control. It fires when the button changes DirtyState, both when it becomes clean and when it becomes dirty. In the EventArgs, you get the state as a boolean plus the control that caused the change. In the demo project, you can see how you can find the name of that control.
  • I did some changes in the EndMonitoring routine. In version 1.0, I simply stopped monitoring the controls, but I left the event handlers where they where. In this version, I decided to do some cleaning up, and am now removing the event handlers.
  • Ulan Bator is no longer a country but a city... It is far away, though... ;-)

Possible improvements in upcoming versions

The ability to add custom and third party controls to the monitoring process would be nice, but was not necessary for me at this stage.

Collections for MonitoredControls, DirtyControls etc. as per request... :-)

As it is now, controls that are added at runtime aren't included unless you call the StartMonitoring method after they are added. But, how often do you add controls at runtime?


  • 2.0: Bug fixes and new functions added. Please see the text above.
  • 1.0: Initial release.


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


About the Author

Johnny J.
Software Developer (Senior)
Sweden Sweden
Born in Copenhagen, Denmark
Have been living in Paris, France and L.A., The United States
Now live in Stockholm, Sweden

Started programming when I got my first VIC 20, and a few months later on Commodore 64. Those were the days!

Studied programming at the Copenhagen Engineering Academy

Professional console, winforms and webforms programming in Comal, x86 Assembler, Fortran, Pascal, Delphi, Visual Basic 3 through 6, Classic ASP, C# and VB.NET

I now work as Senior Microsoft Dynamics AX and .Net programmer, and have a number of projects in various states of progress to work on in the spare time...

Comments and Discussions

GeneralAdd SelectedIndexChanged for ComboBoxes Pin
dreamgarden6-Nov-09 11:35
Memberdreamgarden6-Nov-09 11:35 
QuestionI love this concept (How about a C# version) Pin
solaadio29-Oct-09 3:02
Membersolaadio29-Oct-09 3:02 
AnswerRe: I love this concept (How about a C# version) Pin
Johnny J.16-Apr-10 0:36
professionalJohnny J.16-Apr-10 0:36 
GeneralVery Cool! Pin
hayes.adrian17-Sep-08 11:21
Memberhayes.adrian17-Sep-08 11:21 
GeneralTotal newb Pin
sananelan28-Mar-08 11:07
Membersananelan28-Mar-08 11:07 
GeneralRe: Total newb Pin
Johnny J.30-Mar-08 22:44
professionalJohnny J.30-Mar-08 22:44 
GeneralRe: Total newb Pin
sananelan31-Mar-08 8:01
Membersananelan31-Mar-08 8:01 
GeneralJust a thought Pin
mr_lasseter26-Jun-07 5:58
Membermr_lasseter26-Jun-07 5:58 
GeneralRe: Just a thought Pin
Johnny J.26-Jun-07 6:16
professionalJohnny J.26-Jun-07 6:16 
GeneralRe: Just a thought Pin
mr_lasseter26-Jun-07 10:09
Membermr_lasseter26-Jun-07 10:09 
GeneralTha Tag is saved Pin
Johnny J.26-Jun-07 5:07
professionalJohnny J.26-Jun-07 5:07 
Questionsome suggestions Pin
-tusk-17-Apr-07 16:51
Member-tusk-17-Apr-07 16:51 
AnswerRe: some suggestions Pin
Johnny J.18-Apr-07 4:51
professionalJohnny J.18-Apr-07 4:51 
GeneralRe: some suggestions Pin
-tusk-18-Apr-07 18:43
Member-tusk-18-Apr-07 18:43 
QuestionWhat about? Pin
Civilised Barbarian17-Apr-07 5:26
MemberCivilised Barbarian17-Apr-07 5:26 
AnswerRe: What about? Pin
Johnny J.17-Apr-07 6:03
professionalJohnny J.17-Apr-07 6:03 
AnswerRe: What about? Pin
Civilised Barbarian25-Apr-07 2:40
MemberCivilised Barbarian25-Apr-07 2:40 
GeneralVery good.. Pin
Naresh Mehta16-Apr-07 22:26
MemberNaresh Mehta16-Apr-07 22:26 
GeneralBytheway Pin
gdpaul12-Apr-07 10:56
Membergdpaul12-Apr-07 10:56 
GeneralRe: Bytheway Pin
Johnny J.12-Apr-07 11:51
professionalJohnny J.12-Apr-07 11:51 
QuestionAnother Option? Pin
gklesczewski12-Apr-07 9:13
Membergklesczewski12-Apr-07 9:13 
AnswerRe: Another Option? [modified] Pin
Johnny J.12-Apr-07 10:19
professionalJohnny J.12-Apr-07 10:19 
QuestionAny source code? Pin
ellios12-Apr-07 1:53
Memberellios12-Apr-07 1:53 
AnswerRe: Any source code? Pin
Johnny J.12-Apr-07 4:05
professionalJohnny J.12-Apr-07 4:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.