我有两个日期字段:StartDate和EndDate。 StartDate必须早于EndDate。
如果用户将StartDate更改为大于EndDate的值,则DatePicker周围会出现红色边框,反之亦然。如果用户更改第二个框以使日期范围现在正确,则第一个框仍然具有验证错误。
如果其中任何一个更改,我如何验证两个日期字段?
我正在使用IDataErrorInfo
public string GetValidationError(string propertyName)
{
switch (propertyName)
{
case "StartDate":
if (StartDate > EndDate)
s = "Start Date cannot be later than End Date";
break;
case "EndDate":
if (StartDate > EndDate)
s = "End Date cannot be earlier than Start Date";
break;
}
return s;
}
我不能简单地引发一个PropertyChange事件,因为当它们中的任何一个发生变化时我需要验证这两个字段,因此让两个字段为另一个引发PropertyChange事件将陷入无限循环。
如果另一个日期返回验证错误,我也不喜欢清除Date字段的想法。
答案 0 :(得分:15)
最简单的方法是在设置器中为需要验证的两个属性bathineni suggests
提出PropertyChanged
通知
private DateTime StartDate
{
get { return _startDate; }
set
{
if (_startDate != value)
{
_startDate = value;
RaisePropertyChanged("StartDate");
RaisePropertyChanged("EndDate");
}
}
}
private DateTime EndDate
{
get { return _endDate; }
set
{
if (_endDate!= value)
{
_endDate= value;
RaisePropertyChanged("StartDate");
RaisePropertyChanged("EndDate");
}
}
}
但是,如果这对您不起作用,我想出了一种方法来同时验证一组属性,尽管除了INotifyPropertyChanging
之外,您的类还必须实现INotifyPropertyChanged
(我正在使用EntityFramework,默认情况下,它们的类实现两个接口)
扩展方法
public static class ValidationGroup
{
public delegate string ValidationDelegate(string propertyName);
public delegate void PropertyChangedDelegate(string propertyName);
public static void AddValidationGroup<T>(this T obj,
List<string> validationGroup, bool validationFlag,
ValidationDelegate validationDelegate,
PropertyChangedDelegate propertyChangedDelegate)
where T : INotifyPropertyChanged, INotifyPropertyChanging
{
// This delegate runs before a PropertyChanged event. If the property
// being changed exists within the Validation Group, check for validation
// errors on the other fields in the group. If there is an error with one
// of them, set a flag to true.
obj.PropertyChanging += delegate(object sender, PropertyChangingEventArgs e)
{
if (validationGroup.Contains(e.PropertyName))
{
foreach(var property in validationGroup)
{
if (validationDelegate(property) != null)
{
validationFlag = true;
break;
}
}
}
};
// After the Property gets changed, if another field in this group was
// invalid prior to the change, then raise the PropertyChanged event for
// all other fields in the Validation Group to update them.
// Also turn flag off so it doesn't get stuck in an infinite loop
obj.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
{
if (validationGroup.Contains(e.PropertyName))
{
if (validationFlag && validationDelegate(e.PropertyName) == null)
{
validationFlag = false;
foreach(var property in validationGroup)
{
propertyChangedDelegate(property);
}
}
}
};
}
}
要使用它,请将以下调用添加到应该一起验证一组属性的任何类的构造函数。
this.AddValidationGroup(
new List<string> { "StartDate", "EndDate" },
GetValidationError, OnPropertyChanged);
我在验证组中使用最多3个属性对此进行了测试,它似乎工作正常。
答案 1 :(得分:2)
使用此技巧,它可以防止他们互相调用OnPropertyChanged:
private bool RPCfromStartDate = false;
private bool RPCfromEndDate = false;
public string this[string columnName]
{
get
{
string result = null;
switch (columnName)
{
case "StartDate":
if (StartDate.Date >= EndDate.Date)
{
result = "Start Date cannot be later than End Date";
}
if (!RPCfromEndDate)
{
RPCfromStartDate = true;
OnPropertyChanged("EndDate");
RPCfromStartDate = false;
}
case "EndDate":
if (StartDate.Date >= EndDate.Date)
{
result = "End Date cannot be earlier than Start Date";
}
if (!RPCfromStartDate)
{
RPCfromEndDate = true;
OnPropertyChanged("StartDate");
RPCfromEndDate = false;
}
break;
}
...
答案 2 :(得分:0)
我通常会将所有验证错误添加到字典中,并让验证模板通过属性名称订阅。在每个属性更改事件处理程序中,我可以检查任意数量的属性,并根据需要添加或删除其验证状态。
检查this answer我的实施情况。对不起,它是在VB.NET中,但应该相当简单。
答案 3 :(得分:-1)
您还可以订阅SelectedDateChanged事件处理程序并更新所需的绑定。
private boolean cookieAdded;
...
WebResponse webResponse = (WebResponse) RequestCycle.get().getResponse();
if (!cookieAdded) {
Cookie cookie = new Cookie("foo", "bar");
webResponse.addCookie(cookie);
cookieAdded = true;
}