通过比较一个实体与另一个实体的属性进行验证

时间:2011-11-28 15:39:13

标签: wpf validation

这就是我所拥有的:

在视图中有一个选项卡控件,其中包含两个选项卡(sys1和sys2),每个选项卡都具有绑定到各自实体属性的相同文本框:

SYS1:

<TextBox Text="{Binding sys1.Serial, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />

SYS2:

<TextBox Text="{Binding sys2.Serial, ValidatesOnExceptions=True, NotifyOnValidationError=True}" />

使用某种形式的验证我想比较这两个值,如果值不匹配则显示错误(红色边框很好)。

之前我曾使用过IDataErrorInfo,但我不确定这种验证方式是否可行。

注意:直接绑定到实体是否“正确”是对另一个地点和时间的讨论。只要知道这是一个团队项目,我们的团队标准是绑定到实体,所以我不能改变它,除非我有充分的理由。也许如果直接绑定到实体时无法验证,那么我可能有足够的理由来改变它。

由于

2 个答案:

答案 0 :(得分:1)

我经常从我的模型公开一个Validation Delegate,我的ViewModel可以使用它来将业务规则验证附加到模型。

例如,包含对象的ViewModel可能如下所示:

public ParentViewModel()
{
    sys1.AddValidationErrorDelegate(ValidateSerial);
    sys2.AddValidationErrorDelegate(ValidateSerial);
}

private string ValidateSerial(object sender, string propertyName)
{
    if (propertyName == "Serial")
    {
        if (sys1.Serial == sys2.Serial)
            return "Serial already assigned";
    }
    return null;
}

这个想法是你的Model应该只包含原始数据,因此它应该只验证原始数据。这可以包括验证最大长度,必填字段和允许字符等内容。业务逻辑(包括业务规则)应在ViewModel中进行验证,这样才能实现。

IDataErrorInfo课程Model的实际实现如下:

#region IDataErrorInfo & Validation Members

/// <summary>
/// List of Property Names that should be validated
/// </summary>
protected List<string> ValidatedProperties = new List<string>();

#region Validation Delegate

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

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

public void AddValidationErrorDelegate(ValidationErrorDelegate func)
{
    _validationDelegates.Add(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)
{
    // If user specified properties to validate, check to see if this one exists in the list
    if (ValidatedProperties.IndexOf(propertyName) < 0)
    {
        //Debug.Fail("Unexpected property being validated on " + this.GetType().ToString() + ": " + propertyName);
        return null;
    }

    string s = null;

    // If user specified a Validation method to use, Validate property
    if (_validationDelegates.Count > 0)
    {
        foreach (ValidationErrorDelegate func in _validationDelegates)
        {
            s = func(this, propertyName);
            if (s != null)
            {
                return s;
            }
        }
    }

    return s;
}

#endregion // IDataErrorInfo for binding errors

#region IsValid Property

public bool IsValid
{
    get
    {
        return (GetValidationError() == null);
    }
}

public string GetValidationError()
{
    string error = null;

    if (ValidatedProperties != null)
    {
        foreach (string s in ValidatedProperties)
        {
            error = GetValidationError(s);
            if (error != null)
            {
                return error;
            }
        }
    }

    return error;
}

#endregion // IsValid Property

#endregion // IDataErrorInfo & Validation Members

P.S。我认为直接绑定到Model没有任何问题,特别是在较小的应用程序中。它可能不是“MVVM-purist”方法,但它有效且工作量少,所以我觉得它是一个非常有效的选择。

答案 1 :(得分:0)

在sys1.Serial1和sys2.Serial的set(mutator)中,您应该能够获得另一个值进行比较。