C# 使用IDataErrorInfo在验证期间启用禁用保存按钮

C# 使用IDataErrorInfo在验证期间启用禁用保存按钮,c#,wpf,mvvm,light,C#,Wpf,Mvvm,Light,如何在使用IDataErrorInfo进行验证时禁用/启用按钮 我正在使用MVVM使用GalaSoft light框架。在我的模型类中,我实现了IDataErrorInfo来显示错误消息 public string this[string columnName] { get { Result = null; if (columnName == "FirstName") { if (String.IsNullO

如何在使用
IDataErrorInfo
进行验证时禁用/启用按钮

我正在使用
MVVM
使用GalaSoft light框架。在我的模型类中,我实现了
IDataErrorInfo
来显示错误消息

public string this[string columnName]
{
    get
    {
        Result = null;
        if (columnName == "FirstName")
        {
            if (String.IsNullOrEmpty(FirstName))
            {
                Result = "Please enter first name";
            }
        }
        else if (columnName == "LastName")
        {
            if (String.IsNullOrEmpty(LastName))
            {
                Result = "Please enter last name";
            }
        }

        else if (columnName == "Address")
        {
            if (String.IsNullOrEmpty(Address))
            {
                Result = "Please enter Address";
            }
        }

        else if (columnName == "City")
        {
            if (String.IsNullOrEmpty(City))
            {
                Result = "Please enter city";
            }
        }

        else if (columnName == "State")
        {
            if (State == "Select")
            {
                Result = "Please select state";
            }
        }

        else if (columnName == "Zip")
        {
            if (String.IsNullOrEmpty(Zip))
            {
                Result = "Please enter zip";

            }
            else if (Zip.Length < 6)
            {
                Result = "Zip's length has to be at least 6 digits!";

            }
            else
            {
                bool zipNumber = Regex.IsMatch(Zip, @"^[0-9]*$");

                if (zipNumber == false)
                {
                    Result = "Please enter only digits in zip";


                }
            }
        }
        else if (columnName == "IsValid")
        {
            Result = true.ToString();
        }

        return Result;

    }
}
public string此[string columnName]
{
得到
{
结果=空;
如果(columnName==“FirstName”)
{
if(String.IsNullOrEmpty(FirstName))
{
结果=“请输入名字”;
}
}
else if(columnName==“LastName”)
{
if(String.IsNullOrEmpty(LastName))
{
结果=“请输入姓氏”;
}
}
else if(columnName==“地址”)
{
if(String.IsNullOrEmpty(Address))
{
结果=“请输入地址”;
}
}
else if(columnName==“城市”)
{
if(String.IsNullOrEmpty(城市))
{
结果=“请输入城市”;
}
}
else if(columnName==“State”)
{
如果(状态=“选择”)
{
结果=“请选择状态”;
}
}
else if(columnName==“Zip”)
{
if(String.IsNullOrEmpty(Zip))
{
Result=“请输入zip”;
}
否则如果(拉链长度<6)
{
结果=“Zip的长度必须至少为6位!”;
}
其他的
{
boolzipnumber=Regex.IsMatch(Zip,@“^[0-9]*$”;
if(zipNumber==false)
{
结果=“请仅在zip中输入数字”;
}
}
}
else if(columnName==“IsValid”)
{
结果=true.ToString();
}
返回结果;
}
}
截图:

如何禁用/启用保存按钮。好心的建议


谢谢

您可以添加一个布尔属性,然后在Validation方法的末尾保存并设置它。将IsEnabled从按钮绑定到IsValid。 像这样的事情:

public bool CanSave
{
  get{ return canSave; }
  set{ canSave = value; RaisePropertyChanged( "CanSave" ); }
}
private bool canSave;

public string this[string columnName]
{
  //....
  CanSave = Result == String.Empty;
}

//xaml
<Button IsEnabled={Binding Path=CanSave}>Save</Button>
public bool可以保存
{
获取{return canSave;}
设置{canSave=value;RaisePropertyChanged(“canSave”);}
}
私人布尔可以节省;
公共字符串此[string columnName]
{
//....
CanSave=Result==String.Empty;
}
//xaml
拯救
这样做的目的是在模型中创建以下方法:

static readonly string[] ValidatedProperties =
{
    "Foo",
    "Bar"
};

/// <summary>
/// Returns true if this object has no validation errors.
/// </summary>
public bool IsValid
{
    get
    {
        foreach (string property in ValidatedProperties)
        {

            if (GetValidationError(property) != null) // there is an error
                return false;
        }

        return true;
    }
}

private string GetValidationError(string propertyName)
{
    string error = null;

    switch (propertyName)
    {
        case "Foo":
            error = this.ValidateFoo();
            break;

        case "Bar":
            error = this.ValidateBar();
            break;

        default:
            error = null;
            throw new Exception("Unexpected property being validated on Service");
    }

    return error;
}
/// <summary>
/// Checks if all parameters on the Model are valid and ready to be saved
/// </summary>
protected bool CanSave
{
    get
    {
        return modelOfThisVM.IsValid;
    }
}
最后,如果使用的是
RelayCommand
,则可以将命令的谓词设置为
CanSave
属性,视图将自动启用或禁用该按钮。在ViewModel中:

/// <summary>
/// Saves changes Command
/// </summary>
public ICommand SaveCommand
{
    get
    {
        if (_saveCommand == null)
            _saveCommand = new RelayCommand(param => this.SaveChanges(), param => this.CanSave);

        return _saveCommand;
    }
}
//
///“保存更改”命令
/// 
公共ICommand SaveCommand
{
得到
{
如果(_saveCommand==null)
_saveCommand=newrelaycommand(param=>this.SaveChanges(),param=>this.CanSave);
返回_saveCommand;
}
}
并且认为:

<Button Content="Save" Command="{Binding Path=SaveCommand}"/>

就这样


PS:如果你还没有读过Josh Smith的文章,它将改变你的生活。

以下是我使用IDataErrorInfo接口、ValidationErrors字典和MVVM Light消息系统组合的方法。直截了当,工作起来很有魅力:

模型类

public Dictionary<string, string> ValidationErrors = new Dictionary<string, string>();

public string this[string columnName]
{
  get
   {
     // Remove Property error from ValidationErrors prior to any validation
     ValidationErrors.Remove(propertyName);
     //----------------------------------------
     string Result = null;
     if (columnName == "FirstName")
     {
        if (String.IsNullOrEmpty(FirstName))
        {
           // Add Property error to ValidationErrors Dic
           ValidationErrors[propertyName] = Result = "Please enter first name";
           //----------------------------------------
        }
     }
     else if (columnName == "LastName")
     {
        if (String.IsNullOrEmpty(LastName))
        {
          // Add Property error to ValidationErrors Dic
          ValidationErrors[propertyName] = Result = "Please enter last name";
          //----------------------------------------
        }
     }

    // Send MVVM-Light message and receive it in the Code Behind or VM
    Messenger.Default.Send<PersonInfoMsg>(new PersonInfoMsg());
    //----------------------------------------
    return Result;
  }
}
public Dictionary ValidationErrors=new Dictionary();
公共字符串此[string columnName]
{
得到
{
//在进行任何验证之前,从ValidationErrors中删除属性错误
ValidationErrors.Remove(propertyName);
//----------------------------------------
字符串结果=null;
如果(columnName==“FirstName”)
{
if(String.IsNullOrEmpty(FirstName))
{
//将属性错误添加到ValidationErrors Dic
ValidationErrors[propertyName]=Result=“请输入名字”;
//----------------------------------------
}
}
else if(columnName==“LastName”)
{
if(String.IsNullOrEmpty(LastName))
{
//将属性错误添加到ValidationErrors Dic
ValidationErrors[propertyName]=结果=“请输入姓氏”;
//----------------------------------------
}
}
//发送MVVM Light消息并在代码隐藏或VM中接收
senger.Default.Send(newPersonInfo());
//----------------------------------------
返回结果;
}
}
查看隐藏代码

 public partial class PersonInfoView : UserControl
  {
    public PersonInfoView()
    {
        InitializeComponent();
        Messenger.Default.Register<PersonInfoMsg>(this, OnErrorMsg);
    }

    private void OnErrorMsg(PersonInfoMsg)
    {
        // In case of DataGrid validation
        foreach (PersonInfoModel p in GridName.ItemsSource)
        {
            if (p.ValidationErrors.Count == 0)
                SaveBtn.IsEnabled = true;
            else
                SaveBtn.IsEnabled = false;
        }
     }
  }
公共部分类PersonInfo视图:UserControl
{
公共PersonInfo视图()
{
初始化组件();
Messenger.Default.Register(这个,onerrormg);
}
private void OnErrorMsg(PersonInfo消息)
{
//在DataGrid验证的情况下
foreach(GridName.ItemsSource中的PersonInfo模型p)
{
if(p.ValidationErrors.Count==0)
SaveBtn.IsEnabled=true;
其他的
SaveBtn.IsEnabled=false;
}
}
}

如果您使用
IDataErrorInfo
这实际上比接受的答案要好得多。如果您只是像我现在这样使用验证规则属性,您可能必须使用接受的答案:)如果存在多个验证,则不工作。。。此[string columnName]是按属性调用的。因此,如果prop1无效,而prop2有效,则CanSave设置为true。@Petervankem该部分位于
/..
中:每次调用函数时,
结果必须基于先前的结果重新计算。。是的,这是可能的。然而,我认为这太冒险/复杂了。我选择实现@PieterMüller的解决方案。这不是将验证逻辑放在模型中的好方法,因为验证逻辑可能会在不同的场景中发生变化。为简单起见,它可以是
public bool IsValid=>ValidatedProperties.All(p=>GetValid