IsDirty Change Event

IsDirty Change Event

Old forum URL: forums.lhotka.net/forums/t/12594.aspx


Brendt posted on Tuesday, April 22, 2014

Good day.

i would like to get some help on the following. i am working in a WinForms environment application, i have a "Save" button but i would like to enable/disable the button is my object has been changed. i would think that i would need to check the 'IsDirty' flag of my object, is this correct?

if so, how would i get a raised event when my 'IsDirty' property gets changed so that i can enable/disable my save button accordingly?

any help with on this would be much appreciated.

sash_kr replied on Tuesday, April 22, 2014

Maybe you should check "IsDirty" property in "PropertyChanged" event.

Brendt replied on Tuesday, April 22, 2014

Good day sash_kr.

thank you for your reply, i gathered as much. so how would i go about getting the IsDirty changed event in my winforms so that i can enable/disable my button?

sash_kr replied on Tuesday, April 22, 2014

Brendt

Good day sash_kr.

thank you for your reply, i gathered as much. so how would i go about getting the IsDirty changed event in my winforms so that i can enable/disable my button?

 

this.MyBusinessObject.PropertyChanged +=  MyBusinessObject_PropertyChanged;

 

void   MyBusinessObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
      this.btnSave.Enabled = this.MyBusinessObject.IsDirty;
}

JonnyBee replied on Tuesday, April 22, 2014

It is better to use the BindingSource. 

If you attach events directly between the form and the business object you must also unsubscribe before Save or else the automatic Clone will fail (and try to serialize the form and controls which are NOT serializable). 

The BindingSource is your "connection" to the Business Object and is where you should attach your events to.
The BindingSource also contains a "currency manager" and keep track of the "current" object if you are editing in a list. 
So all you need to do is to hook into the BindingSource.CurrentItemChanged and this can even be done in the designer.  

 

Brendt replied on Wednesday, April 23, 2014

Good day JonnyBee.

Thank you for your Answer, i am still a bit stumped on how to achieve this. i have placed this line of code in my form load which disables the save button, but when i make a change (eg remove a line) BTW this is an invoice form with invoice lines, the save button does not become active again.

cmdSave.DataBindings.Add("Enabled", InvoiceObject, "IsDirty");

i checked, the state when form loads of 'IsDirty' = False and once a line is removed the 'IsDirty' state does change to True but the button does not get enabled. the button does however become enabled if i change a property in the Invoice object (and 'IsDirty' = True). but then if i click save and the object 'IsDirty' = False again the button does not become disabled again. i have added the following lines as well.

public event EventHandler CurrentChanged;

AND

void bindingSource_CurrentChanged(object sender, EventArgs e)
        {
            //this.cmdSave.Enabled = this.qu.IsDirty;
            MessageBox.Show("Binding source firing");

        }

but nothing happens...please could you provide me with more information on this.

JonnyBee replied on Wednesday, April 23, 2014

CSLA does not support databinding to the "status" properties (like IsDirty). 

You must add this in code inside the BindingSource.CurrentItemChanged,

Example:

private void rootBindingSource_CurrentItemChanged(object sender, System.EventArgs e)
{
    var bindingSource = (BindingSource) sender;
    // if there is no "current" item in currency manager?
    if (bindingSource.Position < 0)
    {
        cmdSave.Enabled = false;
        return;
    }
 
    // get the current businessobject and set button enabled if object IsSavable 
    // that is both IsDirty and IsValid.
    var bo = (Csla.Core.ITrackStatus) bindingSource.Current;
    cmdSave.Enabled = bo.IsSavable;
}

Brendt replied on Wednesday, April 23, 2014

Hi JonnyBee.

Thanks for your reply... One other question, what is 'rootBindingSource'? would it be my Invoice Object?

[EDIT]

OK so i have added the BindingSource object onto the form and using its 'CurrentItemChanged' but it only seems to get fired when my form loads. but it doesn't fire when the IsDirty or IsSavable actually changes.

i used this line to set its datasource in the form Load event.

this.bs.DataSource = this.Invoice;

why would this be happening?

JonnyBee replied on Wednesday, April 23, 2014

Yes, you may need to add this to the child bindingsources as well.

When you have a parent and child bindingsource then the parent does not field CurrentItemChanged when a property/item is changed in the child list.

Brendt replied on Wednesday, April 23, 2014

hi JonnyBee.

ok, this is becoming most frustrating...i have added another bindingsource object and set it to my child (lines) object but it do only fires on loading the form. Both 'CurrentItemChanged' events only fire on load or if a property is changed. It doesn't seem to fire when lines are removed.

JonnyBee replied on Thursday, April 24, 2014

Can you provide a sample solution that shows the issues? 

(I will be travelling until next monday without PC so will not be able to look at solution until next week).

Brendt replied on Thursday, April 24, 2014

hi JonnyBee.

this is the bindingSource objects created.

private void lines_CurrentItemChanged(object sender, EventArgs e)
        {
            var bindingSource = (BindingSource)sender;
            // if there is no "current" item in currency manager?
            if (bindingSource.Position < 0)
            {
                cmdSave.Enabled = false;
                return;
            }

            // get the current businessobject and set button enabled if object IsSavable
            // that is both IsDirty and IsValid.
            var bo = (Csla.Core.ITrackStatus)bindingSource.Current;
            cmdSave.Enabled = bo.IsSavable;

            MessageBox.Show("Lines Firing");

        }

        private void root_CurrentItemChanged(object sender, EventArgs e)
        {
            var bindingSource = (BindingSource)sender;
            // if there is no "current" item in currency manager?
            if (bindingSource.Position < 0)
            {
                cmdSave.Enabled = false;
                return;
            }

            // get the current businessobject and set button enabled if object IsSavable
            // that is both IsDirty and IsValid.
            var bo = (Csla.Core.ITrackStatus)bindingSource.Current;
            cmdSave.Enabled = bo.IsSavable;

         



            MessageBox.Show("Root Firing");
        }

and this is how i am setting it in the Form Load event

this.root.DataSource = InvoiceObject;
this.lines.DataSource = InvoiceObject.LineList;

JonnyBee replied on Tuesday, April 22, 2014

Hi,

Normally you will use a BindingSource in your form for DataBinding and you should hook into the CurrentItemChanged event on the BindingSource and set enabled on the button.

See also: http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.currentitemchanged(v=vs.110).aspx

Copyright (c) Marimer LLC