Dailycode.info

Short solution for short problems

Track changes without binding controls

When you are working with windows forms .net without binding your controls to a data object, you still need to check if a control is changed or not. For example if a user closes a form without saving it, you might want to tell the user this and ask him to save or not.

This post will show you a very simple implementation that will easy the development effort. To use this, you will need to create control wrappers for every control that you want to auto implement the track changes functionality.

Let’s begin with creating or modifying an interface that is implemented by all controls that need change tracking. I will add the property IsDirty to the interface. The interface is called: IControlBase

 

#region Properties

 

bool IsDirty { get; set; }

 

#endregion

 

Next we implement the interface in our controls and set the IsDirty flag whenever a value is changed. I will give 2 examples:

Textbox:

#region Implementation of IControlBase

 

public bool IsDirty

{

    get;

    set;

}

#endregion

protected override void OnKeyPress(KeyPressEventArgs e)

{

    IsDirty = true;

    base.OnKeyPress(e);

}

 

Combobox:

#region Implementation of IControlBase

 

public bool IsDirty

{

    get;

    set;

}

 

 

protected override void OnTextChanged(EventArgs e)

{

    IsDirty = true;

    base.OnTextChanged(e);

}

 

So this will make sure that the events we want will set the IsDirty flag. For the combobox I had the problem that the event was raised when I filled it, so I created a function that will clear all IsDirty flags after loading the form:

 

public static void ClearIsDirty(Control currentControl)

{

 

    foreach (Control isDirtyctrl in currentControl.Controls)

    {

        if (isDirtyctrl.Controls.Count > 0)

        {

            ClearIsDirty(isDirtyctrl);

        }

        if (isDirtyctrl.Parent as IControlBase != null)

        {

            ((IControlBase)isDirtyctrl.Parent).IsDirty = false;

        }

    }

}

 

After the page is loaded and all controls are filled, I simply run this function and pass the parent control to it. So it will clear itself and all child controls. The control could be a panel or the form itself:

GlobalFunctions.ClearIsDirty(tpGeneral);

 

Then the last piece of code needs to be written when the user leaves the form without saving. So the onleave of your control is captured and then we call a second function that will check all controls of the form on their IsDirty flag. Here is the function that does the trick, put this function somewhere in your general functions namespace.

private static bool _isDirty=false;

 

public static bool CheckIsDirty(Control currentControl)

{

 

    if ((_isDirty == true))

    {

        return _isDirty;

    }

 

    foreach (Control isDirtyctrl in currentControl.Controls)

    {

        if (isDirtyctrl.Controls.Count > 0)

        {

            CheckIsDirty(isDirtyctrl);

        }

        else

        {

            if (isDirtyctrl.Parent as IControlBase != null)

            {

                if ((((IControlBase)isDirtyctrl.Parent).IsDirty == true))

                {

                    _isDirty = true;

                    return _isDirty;

                }

            }

        }

    }

    return _isDirty;

}

 

Here is the implementation of this function (I check 2 tabpages on the IsDirtyFlag, if the user wants to save I save the project. At the end I clear the IsDirty flags):

private void tbcontProject_Leave(object sender, EventArgs e)

{

    if (GlobalFunctions.CheckIsDirty(tpGeneral) || GlobalFunctions.CheckIsDirty(tpInfo))

    {

        DialogResult res = MessageBox.Show("Information has been changed, do you want to save?", "Information changed", MessageBoxButtons.YesNo);

        if (res == DialogResult.Yes)

        {

            SaveProject();

        }

        GlobalFunctions.ClearIsDirty(tpGeneral);

        GlobalFunctions.ClearIsDirty(tpInfo);

    }