使用IDataErrorInfo和MVVM Pattern问题进行数据验证

时间:2011-06-07 17:13:32

标签: .net wpf validation mvvm

我在WPF MVVM应用程序上使用IDataErrorInfo验证数据时遇到WEIRD问题,我正在做的是:

要验证的属性

public Decimal GlassPrice
    {
        get
        {
            return _GlassPrice;
        }
        set
        {
            if (_GlassPrice != value)
            {
                _GlassPrice = value;
                OnPropertyChanged("GlassPrice");
                CarName = allPropertiesValid.ToString();
            }
        }
    }

“我将在上面的”Set“函数CarName = .. etc中解释最后一行” 然后,一个bool变量,默认值为false,表示所有要验证的属性是否为真,在canExecute函数中使用。

public bool allPropertiesValid
    {

        get { return _allPropertiesValid; }
        set
        {
            if (_allPropertiesValid != value)
            {
                _allPropertiesValid = value;
                OnPropertyChanged("allPropertiesValid");
            }
        }
    }

然后是一个字典,用于保存具有bool值的属性名称对,如下所示

 validAllProperties = new Dictionary<string, bool>();
 validAllProperties.Add("GlassPrice", false);

然后,当然是一种验证属性的方法如下

private string validateGlassPrice()
    {
        if (GlassPrice <= 0)
        {
            return "price can't be 0 nor a minus value ";
        }
        else
        {
            return String.Empty;
        }   
    }

然后在IDataErrorInfo实现

string IDataErrorInfo.this[string columnName]
    {
        get
        {
            string error = String.Empty;
            switch (columnName)
            {
                case "GlassPrice":
                error = validateGlassPrice();
                validAllProperties["GlassPrice"] = String.IsNullOrEmpty(error) ? true : false;
                validateAllProperties();
                return error;
                default:
                throw new ApplicationException("Wrong Property name being validated");
            }

        }
    }

最后设置“allPropertiesValid”的最终值的方法取决于字典中的bool值

private void validateAllProperties()
    {
        foreach (bool isValid in validAllProperties.Values)
        {
            if (isValid == false)
            {
                allPropertiesValid = false;
                return;
            }
        }
        allPropertiesValid = true;
    }

CarName我说我稍后会解释是绑定到textBox的属性,我现在用它来跟踪运行时的“allPropertiesValid”值,所以我让canExecute方法返回“allPropertiesValid”并依赖于与命令关联的按钮将被启用/禁用,这个场景工作正常,我已经使用它完成了3或4个表单并且它们完美地工作,但是在这个特定的一个它没有,在修改之后,事实证明问题只出现在这个特定的属性“GlassPrice”上,我禁用了其他属性的所有验证,并且只是将其保留在此,现在发生的是:当输入1作为值时,Carname给我假,但按钮现在已启用? ?只要CanExecute方法的值为false,就不应该启用该按钮,然后我将0添加为1并且它们变为10然后它变为True,并且无论textBox中的值是否发生变化都保持为True,即使我输入了无效数据如0或null它仍然是真的,按钮总是启用??我坐了几个小时试图解决这个问题,我希望有人可以帮助我

提前致谢

编辑: 那么问题是:如何在TextBox为空时检查Decimal ??,GlassPrice为Decimal且Decimal不接受空值,以下方法检查GlassPrice是否为0或者否,但不是null或空白

private string validateGlassPrice()
    {
        if (GlassPrice <= 0)
        {
            return "price can't be 0 nor a minus value ";
        }
        else
        {
            return String.Empty;
        }   
    }

1 个答案:

答案 0 :(得分:1)

我发布的内容中看不出任何明显错误的内容。以下是一些可以帮助您找到问题的建议:

首先,您要查看的行为(启用/禁用按钮)取决于正在评估的CanExecute并返回正确的值。这真的发生了吗?找出答案的一个好方法是使用CanExecute方法将消息写入控制台,例如:

Console.WriteLine("CanExecute called; returning " + result);
return result;

然后,您可以在使用程序时将“输出”窗口保留在屏幕上,并查看属性是否正在按预期进行评估,以及在评估属性时是否返回值你期待它。

第二个建议是在视图模型中开始使用字符串常量而不是文字。我没有看到你在这里犯了任何错误,但是你发布的代码在三个不同的地方使用字符串文字"GlassPrice"。如果其中任何一个拼写错误,您的代码将以您不期望的方式失败。

最后,两个风格问题 - 这些不是问题的根源,但它们会简化您的代码。这样:

validAllProperties["GlassPrice"] = String.IsNullOrEmpty(error) ? true : false;

应该是这样的:

validAllProperties["GlassPrice"] = String.IsNullOrEmpty(error);

和此:

foreach (bool isValid in validAllProperties.Values)
{
    if (isValid == false)
    {
        allPropertiesValid = false;
        return;
    }
}
allPropertiesValid = true;

可以很容易就是这样:

allPropertiesValid = validAllProperties.Values.All(x => x);