我有一个似乎相当简单的ValidationRule
——我正在尝试验证某个特定日期是否在未来。这里有一个代码示例来说明这个问题:
public class DateNotInTheFutureValidationRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var date = (DateTime)value;
// StackOverflowException here
var now = DateTime.Now;
ValidationResult validationResult = null;
if (date > now)
{
validationResult = new ValidationResult(false, "Cannot be in the future");
}
else
{
validationResult = ValidationResult.ValidResult;
}
return validationResult;
}
}
记录在案,是的,我确实意识到,使用三元形式可以将其中的大部分简化为单个表达式,但这更有助于说明问题。
我将其应用于DatePicker
,如下所示:
<DatePicker Name="startDatePicker" HorizontalAlignment="Left" Margin="89,94,0,0" VerticalAlignment="Top">
<DatePicker.SelectedDate>
<Binding RelativeSource="{RelativeSource Self}" Path="SelectedDate">
<Binding.ValidationRules>
<validationRules:DateNotInTheFutureValidationRule/>
</Binding.ValidationRules>
</Binding>
</DatePicker.SelectedDate>
</DatePicker>
我还有以下风格来处理违反规则的情况:
<Window.Resources>
<Style TargetType="{x:Type DatePicker}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Background" Value="Red" />
<Setter Property="ToolTip"
Value="{Binding RelativeSource={x:Static RelativeSource.Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
奇怪的是:当我在DatePicker
中选择未来的日期时,这就像预期的一样——它毫无例外地运行,并返回正确的ValidationResult
,表明这是不正确的。然而,触发器不起作用——我只收到以下错误消息:
无法从"(Validation.Errors("(类型为"ReadOnlyObservableCollection`1'"(中获取"Item[]"值(类型为ValidationError'(。BindingExpression:路径=(0([0]。ErrorContent;DataItem='DatePicker'(名称='startDatePicker](;目标元素是"DatePicker"(名称="startDatePicker"(;目标属性为"ToolTip"(类型为"Object"(ArgumentOutOfRangeException:"System.ArgumentOut OfRangeException:指定的参数超出了有效值的范围。参数名称:index‘
即使我将ToolTip的setter硬编码为某个文本值而不是进行数据绑定,也不会应用新的样式元素。然而,该代码几乎直接取自文档;我读到的关于这个错误的帖子似乎也表明,这个错误应该只发生在没有验证错误的时候,而不是当有的时候。为什么会发生这种情况?
如果我删除了设置ToolTip
的行,我就不会再收到错误了,但其他setter都没有任何效果——DatePicker
看起来和以前一模一样。
但是,如果我将DatePicker
设置为过去的某个日期,那么当我尝试调用DateTime.Now
时,会出现堆栈溢出异常。
通常,堆栈溢出异常会指示某种无限递归-事实上,当我在这一行设置断点时,它确实,事实上,它会反复被命中,所以看起来这正是发生的事情。
话虽如此,为什么会发生这种情况?调用DateTime.Now
怎么可能导致对Validate方法的递归调用?为什么只有当我过去约会时它才会这么做?
下面的语句将触发无限循环,因为您将属性绑定到自身(SelectedDate(
<Binding RelativeSource="{RelativeSource Self}" Path="SelectedDate">
如果你有datacontext(VM(成员,你可以绑定到它
否则,您可以重新调整现有属性的用途,如下面的"标记",使其在中工作
<Binding RelativeSource="{RelativeSource Self}" Path="Tag">
希望这能有所帮助。
您正在将DatePicker的SelectedDate属性绑定到其自身。(这似乎是堆栈溢出的一个可能原因…(
WPF通常使用MVVM来完成,其中绑定值在ViewModel上,请尝试。