All posts tagged 'mart-client'

.NET Musings

Multi-value Error Conditions with IDataErrorInfo

In my last post on IDataErrorInfo, we implemented the interface and created a custom template for showing the errors.  That works very well for single-valued error checking.  But what if the business logic is conditional (if Field A = x, Field B must be >= y)?  That implementation falls down.  The reason is that WPF only checks the error condition when the PropertyChanged event fires.  The solution is very simple, but does potentially come with a cost.

To illustrate this, we need to update our Product class to include a SalePrice property:

private decimal _salePrice;
public decimal SalePrice
{
    get { return _salePrice; }
    set
    {
        if (_salePrice == value) return;
        _salePrice = value;
        onPropertyChanged(FieldNames.SalePrice);
    }
}

 

The business (albeit the one in my head :-)) has decided if the inventory gets to be over 50 units, then the item must be marked down 10%, but if the count < 50, it should not be marked down at all.  So the following code is introduced to enforce this rule:

case FieldNames.SalePrice:
    if (Inventory > 50 && SalePrice > (Price*.9M))
    {
        return ModelName + " must be marked down due to stock quantity greater than 50";
    }
    if (Inventory < 50 && SalePrice != Price)
    {
        return ModelName + " must not be marked down if the quantity is less than 50";
    }
    break;

 

When we run the form and update the Inventory to 51, we don't get any error indication unless we also update the Sale Price.

 

image

 

We need the PropertyChanged event to fire for the SalePrice property.  But, if we were to add a line in the Inventory and/or Price validations to raise the event, we could end up with an infinite loop as they refer back to each other.

 

Fortunately, the solution is simple.  If we raise the event without a property name in the even arguments, WPF will check all of the properties to see if they have changed.  The cost here is that a lot of potentially needless checking is occurring, so you will have to make a decision if this solution works for you (we will explore other options in future posts).

 

Change the event raiser so that string.empty is passed into the even arguments, and the form works as expected.

private void onPropertyChanged(Enum fieldName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(string.Empty));
    }
}

 

image

 

Happy Coding!

Managed Windows Shared Hosting by OrcsWeb