Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对嵌套对象使用IDataErrorInfo_C#_Mvvm_Idataerrorinfo - Fatal编程技术网

C# 对嵌套对象使用IDataErrorInfo

C# 对嵌套对象使用IDataErrorInfo,c#,mvvm,idataerrorinfo,C#,Mvvm,Idataerrorinfo,我正在使用MVVM,我想使用IDataErrorInfo来验证我的视图 我当前的实现包括嵌套对象和不同的视图模型。e、 g.业务实体“客户”包含业务实体“地址”。我直接在我的视图中访问地址,如“Customer.Address”。为了验证地址中的更改,我必须在地址中实现IDataErrorInfo 我在不同的视图/视图模型中使用客户或地址。在不同视图/视图模型中使用会导致不同的验证行为。因此,在实体本身中实现验证是不够的 在ViewModel中直接暴露我想要更改的属性(创建直接设置/获取实体的新

我正在使用MVVM,我想使用IDataErrorInfo来验证我的视图

我当前的实现包括嵌套对象和不同的视图模型。e、 g.业务实体“客户”包含业务实体“地址”。我直接在我的视图中访问地址,如“Customer.Address”。为了验证地址中的更改,我必须在地址中实现IDataErrorInfo

我在不同的视图/视图模型中使用客户或地址。在不同视图/视图模型中使用会导致不同的验证行为。因此,在实体本身中实现验证是不够的

在ViewModel中直接暴露我想要更改的属性(创建直接设置/获取实体的新属性)似乎会使ViewModel过于僵化。而且太大了

我不能从基类继承,因为一些业务实体已经从其他对象派生(我不能改变这一事实)。 目前我看到的唯一选项是将ViewModel的接口添加到业务实体,并将业务实体中的这个[]调用转发到该ViewModel接口

关于如何在ViewModel中验证这些嵌套对象,是否有最佳做法

编辑:验证我认为业务对象中的验证不可用的另一个原因是,我需要在ViewModel中使用不同的业务对象来验证视图和数据条目

在不同视图/视图模型中使用会导致不同的验证行为

因此,您有不同的视图模型。如果无法从某些基本视图模型继承这些视图模型,请使用聚合:

public class Address {}

public class AddressViewModel1 : IDataErrorInfo
{
  private readonly Address address;
  // other stuff here
}

public class AddressViewModel2 : IDataErrorInfo
{
  private readonly Address address;
  // other stuff here
}

对于每个不同的viewmodel,如何使用依赖项注入并向customer对象注入validationservice


但是我认为在viewmodel中实现idataerrorinfo和所有需要的属性会更干净,但当然还要做一次更多的工作。

我过去这样做的一种方法是,它允许viewmodel将自己的验证代码附加到模型上

通常我这样做是因为我使用
模型
层作为普通数据对象,因此我的模型只验证基本内容,例如最大长度或不为空,而任何不特定于数据模型的高级验证都在ViewModel中完成。这通常包括确保项目是唯一的,或者用户有权将值设置为特定范围,或者类似于您的情况,其中验证仅针对特定操作存在

public class CustomerViewModel
{
    // Keeping these generic to reduce code here, but it
    // should include PropertyChange notification
    public AddressModel Address { get; set; }

    public CustomerViewModel()
    {
        Address = new AddressModel();
        Address.AddValidationDelegate(ValidateAddress);
    }

    // Validation Delegate to validate Adderess
    private string ValidateAddress(object sender, string propertyName)
    {
        // Do your ViewModel-specific validation here.
        // sender is your AddressModel and propertyName 
        // is the property on the address getting validated

        // For example:
        if (propertyName == "Street1" && string.IsNullOrEmpty(Address.Street1))
            return "Street1 cannot be empty";

        return null;
    }
}
以下是我通常用于验证委托的代码:

#region IDataErrorInfo & Validation Members

#region Validation Delegate

public delegate string ValidationDelegate(
    object sender, string propertyName);

private List<ValidationDelegate> _validationDelegates = 
    new List<ValidationDelegate>();

public void AddValidationDelegate(ValidationDelegate func)
{
    _validationDelegates.Add(func);
}

public void RemoveValidationDelegate(ValidationDelegate func)
{
    if (_validationDelegates.Contains(func))
        _validationDelegates.Remove(func);
}

#endregion // Validation Delegate

#region IDataErrorInfo for binding errors

string IDataErrorInfo.Error { get { return null; } }

string IDataErrorInfo.this[string propertyName]
{
    get { return this.GetValidationError(propertyName); }
}

public string GetValidationError(string propertyName)
{
    string s = null;

    foreach (var func in _validationDelegates)
    {
        s = func(this, propertyName);
        if (s != null)
            return s;
    }

    return s;
}

#endregion // IDataErrorInfo for binding errors

#endregion // IDataErrorInfo & Validation Members
#地区IDataErrorInfo和验证成员
#区域验证代表
公共委托字符串验证委托(
对象发送方,字符串propertyName);
私有列表_validationDelegates=
新列表();
public void AddValidationDelegate(ValidationDelegate函数)
{
_validationDelegates.Add(func);
}
public void RemoveValidationDelegate(ValidationDelegate函数)
{
if(_validationDelegates.Contains(func))
_validationDelegates.Remove(func);
}
#endregion//验证委托
#绑定错误的区域IDataErrorInfo
字符串IDataErrorInfo.Error{get{return null;}}
字符串IDataErrorInfo。此[string propertyName]
{
获取{返回this.GetValidationError(propertyName);}
}
公共字符串GetValidationError(字符串属性名称)
{
字符串s=null;
foreach(var func in_validationDelegates)
{
s=func(这是propertyName);
如果(s!=null)
返回s;
}
返回s;
}
#endregion//IDataErrorInfo用于绑定错误
#endregion//IDataErrorInfo和验证成员

这对我来说不是一个有效的解决方案。这使得问题/视图模型比在视图模型本身中公开所需的属性更加严格。澄清一下:有些业务对象(可能)需要添加数百个聚合类,这是我不会做的。而且,在每个ViewModel中使用不同的类也不是我想(也不能)做的事情。@Andreas:为什么这是严格的?您仍然可以从视图中使用VM,如
Customer.Address
,但您可以编写不同的验证行为。@Andreas:您有BO,可以使用100个或更多不同的验证规则集验证它?你能举一个这个对象的例子吗?好吧,我必须为每个ViewModel创建一个不同的AddressViewModel类,从长远来看这是相当混乱的。此外,我还必须补充一点,为了验证大多数对象,我需要ViewModelOK中的其他对象。数百个对象可能有点夸张,因为许多情况可以通过参数显示。但是,这并没有改变我在之前的评论(并在原始帖子中更新)中所述的事实。因此,如果我理解正确的话,“IDataErrorInfo&Validation Members”需要在每个业务实体中实现?由于我不能从任何基对象继承,因此必须将其粘贴到每个实体中。@Andreas我一直在基模型类中使用此代码,并使用
AddValidationDelegate(func)
将验证附加到模型的构造函数中。我想如果您愿意,您也可以将其复制/粘贴到每个类中,并将验证添加到
GetValidationError(propertyName)
方法中,但我认为在基类中实现这一点要好得多。基类会很好,是的,但由于一些限制,我不能保证我能够在模型中使用基类。@Andreas我刚刚重新阅读了你的问题,意识到你说在很多情况下不能从基类继承,所以是的,你必须在模型中复制/粘贴此代码,并确保它们实现
IDataErrorInfo
。我认为,依赖于现有基类的另一种方法是首先扩展基类以添加验证,然后基于扩展基类而不是直接基于基类创建模型。例如,
CustomerModel
可以继承自
ValidatingCustomerBase
Validati