Why is IsDirty == true

Topics: Questions
Mar 5, 2012 at 2:43 PM

Hi,

if I create a new object based on DataObjectBase<Ingredient> from scratch using the parameter less constructor the IsDirty flag is set to true. Why is this so? I thought this would show me if the object was changed....

thanks, Gorroux

Coordinator
Mar 5, 2012 at 5:25 PM

Interesting, I will take a look at this.

See http://catel.codeplex.com/workitem/7091

Coordinator
Mar 5, 2012 at 6:40 PM

Hi Gorroux,

I cannot reproduce your case. Can you please attach the file you use to the issue so I can test that?

Thanks in advance.

Geert

Mar 6, 2012 at 8:18 AM
Edited Mar 6, 2012 at 8:40 AM

I still have this problem in 3.0 beta. I will upload my source a bit later.

Edit:

I now added the project together with some topics/questions.

Coordinator
Mar 6, 2012 at 1:59 PM

Constructor works fine. The issue is that the values are set like this:


Ingredient i1 = new Ingredient { Name = "Methan", DangerClass = 0 };

Then, it creates the class, and then sets the Name and DangerClass (thus the object is dirty). When you call this:

Ingredient i1 = new Ingredient();

IsDirty is false.

 

btw. Catel also contains lots of converters, no need to add these yourself ;)

Converters documentation

Mar 6, 2012 at 2:09 PM

Ahh, stupid me. This makes sense of course. Thanks.

Jul 29, 2012 at 6:52 PM

I did take a look to the sample project http://catel.codeplex.com/workitem/7091 and did read the responses here and did look around the discussions concerning the IsDirty topic. But I still can't imagine how to load the data from the DataObjectBase inheriting entities within the data.cs class respectively to DTO's without to set IsDirty to true. How should the sample project be adapted for a correct implementation of IsDirty? The objective behind that is to know, if the ViewModel or the Model has been modified within a UserControl and to ask the user if he want's to save or cancel.

thanks, Nicolo

Coordinator
Jul 29, 2012 at 7:37 PM

If you have a repro of a model that is dirty immediately, we can take a look at it. You can create a new issue in the issue tracker and upload your files there.

Jul 29, 2012 at 7:53 PM

Seems 'my' issue (http://catel.codeplex.com/discussions/389456) is perhaps facing the same problem? My EF POCO objects (inherited from DataObjectBase) are also always 'IsDirty'.

Hope the repro of nicolo can shed some light on this issue :)

Aug 1, 2012 at 7:00 AM
GeertvanHorrik wrote:

If you have a repro of a model that is dirty immediately, we can take a look at it. You can create a new issue in the issue tracker and upload your files there.

I have created an issue and a sample application here http://catel.codeplex.com/workitem/7179.

Coordinator
Aug 1, 2012 at 10:23 AM

Thank you very much for the clear example. Here is what I did:

1) Create a DTOBase (or ModelBase, whatever you like) with the following code:

 

    public class DTOBase<T> : DataObjectBase<T> 
        where T : class
    {
        protected DTOBase() { }

        protected DTOBase(SerializationInfo info, StreamingContext context)
            : base(info, context) { }

        internal void ClearDirtyFlag()
        {
            IsDirty = false;
        }
    }

 

2) Derive from DTOBase instead of DataObjectBase so the layer that loads the data can clear the IsDirty flag.

3) When loading the data from the database and setting the initial values, use this code:

 

                var company = new DTO.Company()
                {
                    Address = domainEntity.Address,
                    City = domainEntity.City,
                    CompanyID = domainEntity.CompanyID,                    
                    CompanyName = domainEntity.CompanyName,                    
                    PostalCode = domainEntity.PostalCode,
                    PostalCodeAndCity = domainEntity.PostalCodeAndCity
                };

                company.ClearDirtyFlag();

                return company;

 

4) Check the IsDirty of the model, not the view model when checking whether the model is dirty.

 

Then the app works like you expect.

Aug 2, 2012 at 9:35 AM
Edited Aug 2, 2012 at 9:38 AM

Thanks a lot for the fast response and the hints. It now works as i expected.

This is how i did implement now the UpdateCommand in CompanyViewModel.cs:

/// <summary>
/// Gets the UpdateCommand command.
/// </summary>
public Command UpdateCommand { get; private set; }
/// <summary>
/// Method to check whether the UpdateCommand command can be executed.
/// </summary>
/// <returns><c>true</c> if the command can be executed; otherwise <c>false</c></returns>
private bool OnUpdateCommandCanExecute()
{
    return (this.HasDirtyModel);
}
/// <summary>
/// Method to invoke when the UpdateCommand command is executed.
/// </summary>
private void OnUpdateCommandExecute()
{
    if (SelectedCompany.CompanyID != 0)  // Update
    {
        foreach (Company company in CompanyCollection)
        {
            if (company.IsDirty)
            {
                if (companyService.Update(SelectedCompany))
                    SaveViewModel();                        
            }
        }
    }
    else  // Add
    {
        if (companyService.Add(SelectedCompany))
        {
            //SaveViewModel();                    
            var addedID = companyService.Repository.Last().CompanyID;
            SelectedCompany.CompanyID = addedID;
            CompanyCollection.Add(SelectedCompany);
        }
    }
}

The ServiceBase.cs class handels ClearDirtyFlag like this:

public abstract class ServiceBase<TDto, TDomainEntity> : IService<TDto, TDomainEntity>
    where TDto : DTOBase<TDto>
...
    public virtual bool Update(TDto dto)
    {       
        if(repository.Update(assembler.DtoToDomainEntity(dto)))
        {
            dto.ClearDirtyFlag();
            return true;
        }
        return false;
    }

Now the questions:

  1. To be honest i don't understand the significance of the SaveViewModel method. How should it be implemented in the context above?
  2. The HasDirtyModel property seems to be always false. Why?
  3. Is it correct to clear the IsDirty flag like i did?
Coordinator
Aug 2, 2012 at 3:14 PM

1) It is automatically called for you when the user clicks the OK button in the DataWindow. All external controls using a view model should call SaveViewModel at some point, and that is the method where you should save your data. You should not call it yourself inside the view model.

2) Good point, I will look into it.

3) Yep, very good. The only thing I am missing is when you load the object from the db, I cannot see you clear the flag (but probably you just left that code out).