MVVM 模式:如果我们将模型包装在另一个模型中,则 IDataErrorInfo 验证不起作用

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

问题是 UI 上没有显示红色矩形。

我使用 Caliburn.Micro,这就是我的 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>

这里是 ViewModel:

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

这是我在模型中的内容:

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

}

这是另一个 型号:

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

我知道我可以将 IDataErrorInfo 接口从 EditableCustomer 移动到 CustomerInfo 模型,如果我这样做,一切都会完美地工作,但问题是我不允许在 CustomerInfo 模型中进行任何更改,

有人知道我还能做什么吗?

Does anybody have any idea what else I can do?

由于数据绑定 属性 的 class 应该实现 IDataErrorInfo 接口,因此您需要绑定到 EditableCustomer class 的 属性包装 CustomerInfo 模型的名称 属性:

<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)); }
    }

}

您要么必须这样做,要么让 CustomerInfo class 实现 IDataErrorInfo 接口。挑挑拣拣。

在 xaml 中使用 Fluid Validations 会很容易。

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");
 }
}

这将有助于在 wpf 中进行验证。

一旦你提到了 fluidValidations。