/// <summary> /// FormHelper is used to provide dirty checking to input controls on forms. /// /// When initializing a Form class, /// /// HelperClasses.FormHelper formHelper; /// ... /// formHelper = new FormHelper(this); /// formHelper.AddExcludedControl(this.txtRegion); /// formHelper.AddExcludedControl(this.txtPrefecture); /// ... /// // load some form data /// ... /// formHelper.Clean(this) /// ... /// // allow the user to edit /// ... /// if (formHelper.IsDirty(this)) /// { /// // the form is dirty /// } /// </summary> /// <remarks> /// original code from /// http://community.rampgroup.com/blogs/ramp_technology_group/archive/2005/05/03/13.aspx /// </remarks> public class FormHelper { private System.Collections.Specialized.NameValueCollection _checkCollection; private System.Collections.Specialized.NameValueCollection _excludeCollection = new System.Collections.Specialized.NameValueCollection(); /// <summary> /// constructor /// </summary> /// <param name="form"></param> public FormHelper(Control form) { // Initialize _form = form; } #region Public Stuff public Control Form { get { return _form; } set { _form = value; } } private Control _form; private bool _isDirty = false; /// <summary> /// Adds a specific control to an exclusion list. /// </summary> /// <param name="ctl">Control to be excluded.</param> public void AddExcludedControl(Control ctl) { if (ctl is System.Windows.Forms.TextBox || ctl is System.Windows.Forms.ComboBox) { _excludeCollection.Add(ctl.Parent.Name + ctl.Name, ""); } } /// <summary> /// Loop through the controls on a form and save the values in a string array. These are used later for comparison /// to determine whether or not the form is dirty. /// </summary> public void Clean() { Clean(_form); } /// <summary> /// Loop through the controls on a form and save the values in a string array. These are used later for comparison /// to determine whether or not the form is dirty. /// </summary> /// <param name="parent">Control (usually a form) referenced when setting initial values to memory.</param> public void Clean(Control parent) { if (_checkCollection != null) _checkCollection = null; _checkCollection = new System.Collections.Specialized.NameValueCollection(); AddControlsToCollection(parent); _isDirty = false; } /// <summary> /// Determines whether or not the form is dirty by comparing the values set via SetOriginalValues. /// </summary> /// <returns>Returns true if there are one or more controls identified as "dirty".</returns> public bool IsDirty() { if (_isDirty == true) return true; else return IsDirty(_form); } /// <summary> /// Determines whether or not the form is dirty by comparing the values set via SetOriginalValues. /// </summary> /// <param name="parent">Form to check whether dirty or not.</param> /// <returns>Returns true if there are one or more controls identified as "dirty".</returns> public bool IsDirty(Control parent) { if (_isDirty == true) return true; else { if (_checkCollection != null) { foreach (Control ctl in parent.Controls) { _isDirty = IsDirtyControl(ctl); } } } return _isDirty; } /// <summary> /// Determines whether control is dirty /// </summary> /// <param name="ctl"></param> /// <returns>True if control is dirty</returns> public bool IsDirtyControl(Control ctl) { if (_isDirty == true) return true; else { if (_checkCollection != null) { if (ctl is System.Windows.Forms.TextBox || ctl is System.Windows.Forms.MaskedTextBox || ctl is System.Windows.Forms.ComboBox) { if (_checkCollection.Get(ctl.Parent.Name + ctl.Name) != null && _checkCollection.Get(ctl.Parent.Name + ctl.Name) != ctl.Text) { _isDirty = true; } } else if (ctl is System.Windows.Forms.CheckBox) { CheckBox chk = (CheckBox)ctl; if (_checkCollection.Get(ctl.Parent.Name + ctl.Name) != null && _checkCollection.Get(ctl.Parent.Name + ctl.Name) != chk.Checked.ToString()) { _isDirty = true; } } if (ctl.HasChildren == true && IsDirty(ctl) == true) { _isDirty = true; } } } return _isDirty; } #endregion #region Private Methods /// <summary> /// Loop through the controls on a form and save the values in a string array. These are used later for comparison /// to determine whether or not the form is dirty. /// </summary> /// <param name="parent">Control (usually a form) referenced when setting initial values to memory.</param> private void AddControlsToCollection(Control parent) { foreach (Control ctl in parent.Controls) { if (_excludeCollection.Get(parent.Name + ctl.Name) == null) { if ((ctl is System.Windows.Forms.TextBox || ctl is System.Windows.Forms.MaskedTextBox || ctl is System.Windows.Forms.ComboBox)) { _checkCollection.Add(parent.Name + ctl.Name, ctl.Text); } else if (ctl is System.Windows.Forms.CheckBox) { CheckBox chk = (CheckBox)ctl; _checkCollection.Add(parent.Name + ctl.Name, chk.Checked.ToString()); } if (ctl.HasChildren) AddControlsToCollection(ctl); } } } #endregion }2) Initialize FormHelper
/// <summary> /// extended MM business form /// </summary> public class myMaintenanceForm : mmMaintenanceForm { /// <summary> /// myMaintenanceForm constructor /// </summary> public myMaintenanceForm () { // // Required for Windows Form Designer support // InitializeComponent(); // initialize dirty helper this.DirtyHelper = new FormHelper(this); } /// <summary> /// checker for dirty controls /// </summary> public FormHelper DirtyHelper { get { return _dirtyHelper; } set { _dirtyHelper = value; } } private FormHelper _dirtyHelper = null; // ... }3) mmToolStripButton enable/disable
public void SetFormButtons(bool isChanged) { if (this.NavToolBar != null) { this.NavToolBar.Items["btnSave"].Enabled = isChanged; this.NavToolBar.Items["btnCancel"].Enabled = isChanged; this.NavToolBar.Items["btnDelete"].Enabled = !isChanged; } }4) Hook...() methods
protected override void HookPostNavigate() { base.HookPostNavigate(); DirtyHelper.Clean(); } protected override void HookPostCancel(OakLeaf.MM.Main.Business.mmBusinessObject bizObj, string tableName) { base.HookPostCancel(bizObj, tableName); DirtyHelper.Clean(); SetFormButtons(false); } protected override void HookPostNewRow(mmBusinessObject bizObj, string tableName) { base.HookPostNewRow(bizObj, tableName); DirtyHelper.Clean(); this.NavToolBar.SetNavButtonsEnabled(false); SetFormButtons(true); } protected override void HookPostNewRow(mmBusinessObject bizObj, DataView dv) { base.HookPostNewRow(bizObj, dv); DirtyHelper.Clean(); this.NavToolBar.SetNavButtonsEnabled(false); SetFormButtons(true); } protected override void HookPostNew(mmEntityBusinessObject businessObject) { base.HookPostNew(businessObject); DirtyHelper.Clean(); this.NavToolBar.SetNavButtonsEnabled(false); SetFormButtons(true); } protected override void HookPostDelete(mmBusinessObject bizObj, string tableName) { mmBusinessRule Rules = bizObj.GetBusinessRuleObject(); if (Rules != null) { string ErrorMsg = Rules.GetAllBrokenRules(); if (!mmString.Empty(ErrorMsg)) { MessageBox.Show(ErrorMsg, "Can't Delete"); } } base.HookPostDelete(bizObj, tableName); // ??? check behavior // DirtyHelper.Clean(); } protected override void HookPostSave(mmBaseBusinessObject bizObj) { base.HookPostSave(bizObj); DirtyHelper.Clean(); SetFormButtons(false); // this.NavToolBar.SetNavButtonsEnabled(true); } protected override void HookPostSave(mmBusinessObject bizObj) { base.HookPostSave(bizObj); DirtyHelper.Clean(); SetFormButtons(false); // this.NavToolBar.SetNavButtonsEnabled(true); }5) ...Changed() methods in subclasses of controls
// +++ todo: implement: // bool CheckForDirty property, default true // bool IsDirty() or Dirty property private void NumericTextBox_ValueChanged(object sender, EventArgs e) { if (this.Focused) { // +++ todo: check type of form to allow control to be used in other forms myMaintenanceForm Maintform = (myMaintenanceForm)mmAppDesktop.FormMgr.GetParentBusinessForm(this); // allow save, cancel, disallow delete if (Maintform.DirtyHelper.IsDirtyControl(this)) Maintform.SetFormButtons(true); } }