验证WPF应用中的必填字段

时间:2016-10-06 21:33:54

标签: c# wpf

我正在开发一个C#/ WPF应用程序,其中我有多个视图(例如A,B,C等)和相应的视图模型。开发人员也会添加很多新的视图。应用程序在未来。 每个视图都有各种控件,如文本框,组合框,日期时间选择器等。

我尝试为必填字段提出验证方法,以便开发人员需要添加最少量的代码来验证新添加的视图上的控件。

我目前的做法:

我的所有视图模型都继承自名为" ViewModelBase"的基类。我在这个类中添加了一个名为IsRequiredFieldValueBlank()的新方法:

public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
        public bool IsRequiredFieldValueBlank(object inputObject)
        {
            bool isRequiredFieldValueBlank = true;
            try
            {
                var arrProperties = inputObject.GetType().GetProperties();

                foreach (var prop in arrProperties)
                {
                    if (!prop.CanWrite)
                        continue;
                    if(prop.PropertyType.Name.ToUpper() == "STRING")
                    {                        
                        if (string.IsNullOrEmpty(prop.GetValue(inputObject).ToString()))
                        {
                            isRequiredFieldValueBlank = true;
                            break;
                        }
                    }

                }

            }
            catch (Exception ex)
            {
              //TBD:Handle exception here
            }
            return isRequiredFieldValueBlank;
        }
}

在我的xaml View of View" A"中,我提供了以下代码:

<TextBox HorizontalAlignment="Left" Height="23" VerticalAlignment="Top" Width="180" TabIndex="1" Text="{Binding ProductDescription,NotifyOnSourceUpdated=True,  UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource RequiredFieldStyle}" Grid.Row="1"  Grid.Column="3"  Margin="1,10,0,0" />

在我的MainWindoResources.xaml

<Style TargetType="TextBox" x:Key="RequiredFieldStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=ViewModelBase.IsRequiredFieldValueBlank}" Value="false">
                <Setter Property="Background" Value="BurlyWood" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=ViewModelBase.IsRequiredFieldValueBlank}" Value="true">
                <Setter Property="Background" Value="LightGreen" />
                <Setter Property="Foreground" Value="DarkGreen" />
            </DataTrigger>            
        </Style.Triggers>
    </Style>

的App.xaml:

<Application x:Class="MyTool.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             Startup="Application_Startup">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Views/MainWindowResources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>

    </Application.Resources>
</Application>

我的问题: 1.这是正确的方法吗?如果是,那么我理解代码不会工作,因为xaml没有将inpoObject传递给ViewModelBase类中的IsRequiredFieldValueBlank()方法。 有人可以建议如何实现这一目标吗?

2.有没有其他方法可以解决这个问题?

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

如果您将Validator静态类与IDataErrorInfoINotifyPropertyChanged接口结合使用进行验证,则可以使您的生活更轻松。这是一个非常基本的实现扩展PRISM的BindableBase类:

public abstract class ViewModelBase : IDataErrorInfo, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Error => string.Join(Environment.NewLine, GetValidationErrors());

    public bool IsValid => !GetValidationErrors().Any();

    public string this[string columnName] =>
        GetValidationErrors().FirstOrDefault(result => result.MemberNames.Contains(columnName))?.ErrorMessage;

    protected IEnumerable<ValidationResult> GetValidationErrors()
    {
        var context = new ValidationContext(this);
        var results = new List<ValidationResult>();

        Validator.TryValidateObject(this, context, results, true);

        return results;
    }

    protected virtual void OnPropertChanged([CallerMemberName]string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
    {
        if (Equals(storage, value))
        {
            return false;
        }

        storage = value;
        OnPropertChanged(propertyName);
        return true;
    }
}

您也不需要RequiredFieldStyle文件。验证可以这样完成:

public class ViewModelExample : ViewModelBase
{
    private string _myString;

    // do validation with annotations and IValidateableObject
    [Required]
    [StringLength(50)]
    public string MyString
    {
        get { return _myString; }
        set { SetProperty(ref _myString, value); }
    }
}

在保存之前,只需检查IsValid属性以查看对象是否有效。