MVVM pattern: IDataErrorInfo validation doesn't work if we have wrapped model inside another model

859 views Asked by At

The problem is that the red rectangle is not shown on the UI.

I use Caliburn.Micro and this is is what I have in my View:

<StackPanel Grid.Row="0">
     <Label>Customer name:</Label>
     <TextBox x:Name="txtName" Text="{Binding Target.Model.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="136" HorizontalAlignment="Left"/>
</StackPanel>

Here is the ViewModel:

internal class ShellViewModel : Screen
{
    private EditableCustomer _Target;
    public EditableCustomer Target
    {
        get { return _Target; }
        set { if (_Target != value) { _Target = value; NotifyOfPropertyChange(nameof(Target)); } }
    }
}

This is what I have in the Model:

internal class EditableCustomer : PropertyChangedBase, IDataErrorInfo
{
    private CustomerInfo _Model;
    public CustomerInfo Model
    {
        get { return _Model; }
        set { if (_Model != value) { _Model = value; NotifyOfPropertyChange(nameof(Model)); } } 
    }

}

And this is another Model:

internal class CustomerInfo : PropertyChangedBase
{
    private string _Name;
    public string Name
    {
        get { return _Name; }
        set { _Name = value; NotifyOfPropertyChange(nameof(Name)); }
    }
}

I know I can move IDataErrorInfo interface from EditableCustomer to CustomerInfo model and everything will work perfectly if I do so, but the problem is that I'm not allowed to make any change in the CustomerInfo model,

Does anybody have any idea what else I can do?

2

There are 2 answers

0
mm8 On BEST ANSWER

Does anybody have any idea what else I can do?

Since it is the class of the data bound property that should implement the IDataErrorInfo interface you will then need to bind to a property of the EditableCustomer class that wraps the Name property of the CustomerInfo model:

<TextBox x:Name="txtName" Text="{Binding Target.NameWrapper, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" Width="136" HorizontalAlignment="Left"/>

internal class EditableCustomer : PropertyChangedBase, IDataErrorInfo
{
    private CustomerInfo _Model;
    public CustomerInfo Model
    {
        get { return _Model; }
        set { if (_Model != value) { _Model = value; NotifyOfPropertyChange(nameof(Model)); } }
    }

    //bind to this one instead of binding directly to the Name property of the model:
    public string NameWrapper
    {
        get { return _Model.Name; }
        set { _Model.Name = value; NotifyOfPropertyChange(nameof(NameWrapper)); }
    }

}

You will either have to do this or make the CustomerInfo class implement the IDataErrorInfo interface. Pick and choose.

0
raghava arr On

Use Fluid Validations will be easy in xaml.

public class ModelValidator : AbstractValidator<Customer>
{
 public ModelValidator(){
   RuleFor(model => model.Name).NotEmpty().WithMessage("Name is Requried");
   RuleFor(model => model.Age).NotEmpty().WithMessage("Age is Required");
   RuleFor(model => model.Designation).NotEmpty().WithMessage("Choose Your Designation");
 }
}

This will be help for validations in wpf.

Once you refer about fluidValidations.