Newbie Complex Validation Problem

Newbie Complex Validation Problem

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


skumaran24 posted on Wednesday, September 24, 2008

Dear Friends,

I have been using CSLA.NET past few week now and able to understand the basic function and currently using it to develop a software. Everything was going well until i come up with this problem which I'm still not able to solve. I search the forum posting and still unable to find a solution. Here is my problem.

I have 3 classes

Project : BusinessBase

Sample : BusinessBase

Samples : BusinessListBase<Samples, Sample>

Project has a property called SampleSize and Project will have a Samples.

Sample has a property called Allocation.

Samples will have a collection of Sample.

Im displaying SampleSize in a textbox and Samples in a datagridview.I allow user to edit the Allocation field and the SampleSize. Each time the user edit the Allocation or SampleSize i need to perform a validation where the total "allocation" of all the Sample in the Samples object should not be be greater than SampleSize. SampleSize is a property from  Project object.

I need to,

1. Show error in each row after the user edited the "Allocation" value if total allocation is > sampleSize.

2 Show error in each row after the user edited the "SampleSize" value if total allocation is > sampleSize

This means, when ever the user change the allocation it should check weather the total allocation > then the sampleSize, if it is then show error on each row because user maybe can modify any single row and make the allocation valid.

User can either choose to modify the Sample Allocation or the Project SampleSize to make the allocation valid hence removing the error from each now and making the whole object valid again.

Can this be done? Or is there any other way to solve this kind of situation.

I hope i have explain my problem clearly. Please guide me to solve this problem

Thanks.

P.S : I'm using CSLA.NET 2.1.4

triplea replied on Wednesday, September 24, 2008

If I were you I would not mark the whole grid as erroneous (so showing the error icon in each row) but rather only on your SampleSize textbox. Implementing this would be simple:

1. Add the rule logic in Project and assign it to property SampleSize.
2. * Not 100% sure about this bit as I am guessing * Add an event handler for Sample.PropertyChanged on Project. When this get fired, validate the rule for SampleSize again.

This should be sufficient for the errorprovider to show the error next to your SampleSize textbox.

Now if you still want to mark every row as erroneous then I can only think of the following workaround (there are probably better ways):

1. In Project.OnPropertyChanged , when SampleSize is modified then perform your check. If it fails then have a dummy string field in Sample (e.g. ErrorDescription") which has a rule that its length should not be greater than zero and set it to a message from Project. Doing that to all the child records will make them invalid and the error will be shown.
2. Add an event handler for Sample.PropertyChanged on Project. When this get fired, perform the same actions as above.

I guess both ways are not perfect and need tweeking but it should give yuo an idea.

Btw since you are just beginning with CSLA I would suggest you use version 3.0.4 (it works with .Net 2.0 if that is of importance to you) as its the latest stable pre .Net 3.5 version.

skumaran24 replied on Wednesday, September 24, 2008

Hi triplea, thanks alot for the tips. I only want to mark every row as erroneous and this how i solve following the guideline you gave me.

I added this code to the Project object

protected override void AddBusinessRules()

{

               ValidationRules.AddRule<Project>(AllocationGTSampleSize<Project>, "SampleSize");

}

private static bool AllocationGTSampleSize<T>(T target, Csla.Validation.RuleArgs e) where T : Project

{

int totalAllocatedSample = 0;

foreach (Sample sample in target._samples)

{

            totalAllocatedSample = totalAllocatedSample + sample.Allocation;

}

if (totalAllocatedSample > target._sampleSize)

{

            foreach (Sample sample in target._samples)

         {

               sample.ErrorDesc = "1234567890";

            }

            return false;

}

else

{

               foreach (Sample sample in target._samples)

               {

                           sample.ErrorDesc = "";

                  }

return true;

}

}

Added this code at Sample Object

protected override void AddBusinessRules()

{

ValidationRules.AddRule<Sample>(AllocationGTSampleSizeError<Sample>, "ErrorDesc");

}

private static bool AllocationGTSampleSize<T>(

T target, Csla.Validation.RuleArgs e) where T : Sample

{

if (target._errorDesc.Length > 1)

{

e.Description = "Allocation has exceted sample size";

return false;

}

else

{

return true;

}

}

This will trigger the validation where user change the SampleSize

To trigger the event when user change the Allocation on the gridview i added this code to the Project Object

private void DataPortal_Fetch(Criteria criteria)

{

           ....................

              .................

           // load child objects

         dr.NextResult();

        _samples = Samples.GetProjectSamples(dr);

       _samples.ListChanged += new System.ComponentModel.ListChangedEventHandler(_samples_ListChanged);

}

void _samples_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)

{

               if (e.PropertyDescriptor.Name == "Allocation")

              {

                        ValidationRules.CheckRules("SampleSize");

                 }

}

All this code manage to solve my problem. The only thing is that the datagridview show the erroneous only when i move my cursor to it. It does not refresh i guess, I slove this problem by using this code.

private void projectBindingSource_BindingComplete(object sender, BindingCompleteEventArgs e)

{

             dataGridView1.UpdateRowErrorText(0, dataGridView1.RowCount - 1);

}

Basically this solves the problem. Do you think i can apply this solution for my project? Does anyone else have a different idea?

Thanks

triplea replied on Wednesday, September 24, 2008

Not sure but what if you call ValidationRules.CheckRules() (so not the property specific overload) after your fetch from the db is complete?

Also note that depending on the dataportal setup you choose to use, you will have to re hookup the _samples_ListChanged handler. Do that in the OnDeserialized override otherwise you may loose the functionality after a save.

skumaran24 replied on Wednesday, September 24, 2008

Hi again really thanks for the replies its helping me alot to slove this problem.

"Not sure but what if you call ValidationRules.CheckRules() (so not the property specific overload) after your fetch from the db is complete?" (Im not quite sure what you mean)

 re hookup the _samples_ListChanged handler is done like this right?

protected override void OnDeserialized(System.Runtime.Serialization.StreamingContext context)

{

_samples.ListChanged += new System.ComponentModel.ListChangedEventHandler(_samples_ListChanged);

}

Really Thanks

triplea replied on Thursday, September 25, 2008

What I meant was (in your example):

 

private void DataPortal_Fetch(Criteria criteria)
{
      ....................
      
.................

      // load child objects
      
dr.NextResult();

      _samples = Samples.GetProjectSamples(dr);

      _samples.ListChanged += new System.ComponentModel.ListChangedEventHandler(_samples_ListChanged);

      this.ValidationRules.CheckRules();
}

skumaran24 replied on Thursday, September 25, 2008

So far everything works fine. Thanks alot for the help.

Copyright (c) Marimer LLC