I have a model:
public class Product
{
public int Rating { get; set; }
...
}
and a View Model:
public class ProductViewModel: IDataErrorProvider
{
public int Temperature { get; set; }
public Product CurrentProduct { get; set; }
public string this[string columnName]
{
get
{
if (columnName == "Rating")
{
if (CurrentProduct.Rating > Temperature)
return "Rating is too high for current temperature";
}
return null;
}
}
}
My view has an instance of ProductViewModel as the DataContext. The view has the field:
<TextBox Text={Binding Path=CurrentProduct.Rating, ValidatesOnDataErrors=True} .../>
By default, validation occurs on the IDataErrorProvider of the bound object (Product), not the DataContext (ProductViewModel). So in the above instance, ProductViewModel validation is never called. This is just a simple example but illustrates the problem. The model doesn’t (and shouldn’t) know about Temperature, so the design dictates that the VM should perform the validation on that field.
Yes, I could hack it and replicate the bound properties of the model directly in the ViewModel, but I would have thought there must be an easier way to redirect the call to the VM rather than the model?
I’ve encountered that problem before, and my solution is to expose a validation delegate from my
Modelswhich is checked when validating the class, and theViewModelcan use this to hook addition validation to the class that is unrelated toModelitselfFor example, I would use code that looked something like this from the
ViewModelto attach a validation delegate to theModelanytime its setThe actual code that adds the
ValidationDelegateto theModelis pretty generic, so I typically have it in aBaseViewModelso all Models can have this functionality without me having to type it out for each oneI also have this approach outlined in my blog post here if you want to see another example.