我正在开发一个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.有没有其他方法可以解决这个问题?
感谢您的帮助。
答案 0 :(得分:0)
如果您将Validator
静态类与IDataErrorInfo
和INotifyPropertyChanged
接口结合使用进行验证,则可以使您的生活更轻松。这是一个非常基本的实现扩展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
属性以查看对象是否有效。