3

I am using C# Windows Forms (.NET 3.5), and trying to implement the functionality when user modifies any of the data bounded columns on the Detail form, and tries to close the form without saving, system should pop-up my message "Save Changes?".

I know I can always use TextChanged event for Textbox etc., but that requires multiple event coding. I would like to use a specific event handler that detects a change in value in any of the fields that are associated with my BindingSource.

I have bounded my columns like this:

textbox1.DataBindings.Add("Text", this.bindingSource1, "dbcolumn_1", true);
Be Brave Be Like Ukraine
  • 7,596
  • 3
  • 42
  • 66
AGR090808
  • 33
  • 1
  • 3

3 Answers3

1

Would something like this work?

  1. Define a changedFlag variable in your form, default value = false.

    private changedFlag = false; // form value(s) changed, check it on form close

  2. Put this in event handler for an Exit button, or adapt into the form closing handler:

        if (this.changedFlag && MessageBox.Show("Save your changes before exit?", "Save changes?", MessageBoxButtons.OKCancel) == DialogResult.OK)
        {
            this.Save();
        }
    
  3. Create a function that takes a control container and recursively looks through its controls to wireup the change handler (defined in step 4).

    private void AddOnChangeHandlerToInputControls(Control ctrl)
    {
        foreach (Control subctrl in ctrl.Controls)
        {
            if (subctrl is TextBox)
            {
                ((TextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is CheckBox)
            {
                ((CheckBox)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is RadioButton)
            {
                ((RadioButton)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is ListBox)
            {
                ((ListBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is ComboBox)
            {
                ((ComboBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
            }
            else
            {
                if (subctrl.Controls.Count > 0)
                {
                    this.AddOnChangeHandlerToInputControls(subctrl);
                }
            }
        }
    }
    
  4. Create a general change handler function that sets changedFlag = true

    private void InputControls_OnChange(object sender, EventArgs e)
    {
        this.changedFlag = true;
    }
    
  5. As soon as your controls are built (not sure if you are making them dynamically, but you used textbox1 in your example so I'm assuming not), call the function from step 3 and pass in the inputs' container control.

    AddOnChangeHandlerToInputControls(panelFormContainer);

By passing in the form controls' container you avoid manual wire up of the change handler for each control. And remember to modify the Save() function to reset changedFlag = false;

nothingisnecessary
  • 6,099
  • 36
  • 60
0

Define the on_closing event handler; http://msdn.microsoft.com/en-us/library/system.windows.forms.form.onclosing.aspx

Inside of there launch a form asking them if the want to save and open it as a dialogue so the focus is forced on that form (the sample code in the link shows how to do all of this).

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • Thank you for your response. I do have about 80 fields in my form with the mix of TextBox, Combobox, checkbox etc, they all are tied to the BindingSource and DataTable. I am hoping to find a solution that I can just deal with the BindingSource or DataTable, rather than comparing each field with its original value in the on_closing event handler to check if anything was changed. Thanks. – AGR090808 Nov 01 '12 at 01:50
0

The answer from nothingIsNecessary was pretty close but I still had to look around to get it working.

Namely, the issue was

AddOnChangeHandlerToInputControls(panelFormContainer);

should be

AddOnChangeHandlerToInputControls(this);

panelFormContainer wasn't working nor could I find documentation for it.

Reference: Loop through all controls on a form,even those in groupboxes

I also went ahead and added more control types as I needed them. I used MouseCaptureChanged for datePicker since the checkbox would sometimes fire ValueChanged and sometimes it wouldn't. ¯_(ツ)_/¯

private void AddOnChangeHandlerToInputControls(Control ctrl) 
    {
        foreach (Control subctrl in ctrl.Controls)
        {
            if (subctrl is TextBox)
            {
                ((TextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is CheckBox)
            {
                ((CheckBox)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is RadioButton)
            {
                ((RadioButton)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is ListBox)
            {
                ((ListBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is ComboBox)
            {
                ((ComboBox)subctrl).SelectedIndexChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is MaskedTextBox)
            {
                ((MaskedTextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is DateTimePicker)
            {
                ((DateTimePicker)subctrl).MouseCaptureChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is RichTextBox)
            {
                ((RichTextBox)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
            }
            else if (subctrl is NumericUpDown)
            {
                ((NumericUpDown)subctrl).TextChanged += new EventHandler(InputControls_OnChange);
            }
            else
            {
                if (subctrl.Controls.Count > 0)
                {
                    this.AddOnChangeHandlerToInputControls(subctrl);
                }
            }
        }
    }
blind Skwirl
  • 321
  • 3
  • 6