Dependent property question

Dependent property question

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


esteban404 posted on Friday, January 09, 2009

I have questions regarding some dependant property rules for a data entry form where a person gets a form that's incompletely filled in and I'm requested to provide some way to get a best guess input for them based on the input.

Using CSLS 3.0.4 I have three fields: Start, End and Duration which are of types DateTime, DateTime and TimeSpan respectively. The requirements I gleaned are:

* If the user fills in Duration, the object can be saved.
* If the start and end are filled in, I can compute the duration and the object can be saved.
* If they've given me a start and duration, I can compute the end or vice versa, and the object can be saved.
* In any situation where the Duration is not available, it should be invalid and not saveable.

How do I structure the rules to construct a valid object? Do I require Duration and be an error and the other two are warnings only using the property changed to compute the value?

Is this something the BO layer should do or the UI (before save)?

Thanks for any advice,
_E

SonOfPirate replied on Friday, January 09, 2009

I've run into the same scenario in the past and I used nullable variables in the background to track which properties actually had manually entered values and which were derived (per my use case) and always returned a default value so there was never an issue with missing values.  For example, my StartDate property appeared as:

public System.DateTime StartDate
{
    get
    {
        if (_startDate.HasValue)
            return _startDate.Value;
        else if (_endDate.HasValue)
            return _endDate.Value.Subtract(Duration);
        else
            return System.DateTime.Today; // Or something else
    }
    set
    {
        if (value == null)
            _startDate = null;
        else
        (
            _startDate = new System.Nullable<System.DateTime>(value);
 
            if (_endDate.HasValue)
                _duration = null; // forces duration to be derived
        }
    }
}

EndDate would be similar:

public System.DateTime EndDate
{
    get
    {
        if (_endDate.HasValue)
            return _endDate.Value;
        else
            return StartDate.Add(Duration);
    }
    set
    {
        if (value == null)
            _endDate = null;
        else
        (
            _endDate = new System.Nullable<System.DateTime>(value);
 
            if (_startDate.HasValue)
                _duration = null; // forces duration to be derived
        }
    }
}

And Duration would be:

public System.TimeSpan Duration
{
    get
    {
        if (_duration.HasValue)
            return _duration.Value;
        else if (_startDate.HasValue) && (_endDate.HasValue)
            return _endDate.Value.Subtract(_startDate.Value);
        else
            return System.TimeSpan.Zero;
    }
    set
    {
        if (value == null)
            _duration = null;
        else
        (
            _duration = new System.Nullable<System.TimeSpan>(value);
 
            if ((_startDate.HasValue) && (_endDate.HasValue))
                _endDate = null; // forces endDate to be derived
        }
    }
}

This eliminated my need to do any validation except to make sure that the dates were within valid ranges and that the EndDate was always the same or later than the StartDate (and example of which is shown in the book and sample app).

Hope that helps.

 

rsbaker0 replied on Friday, January 09, 2009

You could also do the above with validation rules (including the computation of any two of the fields from the other two). Sometimes you don't have the luxury of tinkering inside the property setter (e.g. code is generated).

The trick in doing this is to avoid getting into some weird infinite loop since the 3 values are interdependent, and to handle the case where no property was changed but someone calls CheckRules() explicitly. Also, you might just have 3 discrete rules and not use the dependencies.

Also, rules don't have to be warnings -- you can have a rule that just does a transformation and always succeeds.

esteban404 replied on Friday, January 09, 2009

Thank you, gentlemen. That gives me a great start. I'm porting some .NET 1.1 code and forget about nullable fields out of habit.

I also think that the start and end field should always have an entry so the production down time can be analyzed with trends to see if production mysteriously ceases at the same time more than it should... say 10 min before end of shift.

Now to do it...

_E

Copyright (c) Marimer LLC