代码之家  ›  专栏  ›  技术社区  ›  EJoshuaS - Stand with Ukraine

WPF数据绑定验证和伴随的数据触发器要么导致堆栈溢出异常,要么没有任何效果

  •  0
  • EJoshuaS - Stand with Ukraine  · 技术社区  · 7 年前

    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>
    

    奇怪的是:当我选择未来的某个日期时 ,这将按预期工作-它毫无例外地运行并返回正确的 ValidationResult

    无法从“(Validation.Errors)”获取“Item[]”值(类型为“ValidationError”)(类型为“ReadOnlyObservableCollection`1”)。BindingExpression:Path=(0)[0]。ErrorContent;DataItem='DatePicker'(Name='startDatePicker');目标元素是“DatePicker”(Name='startDatePicker');目标属性为“ToolTip”(类型为“Object”)ArgumentOutOfRangeException:“System.ArgumentOutOfRangeException:指定的参数超出有效值的范围。 参数名称:索引'

    不要 . 为什么会这样?

    如果我删除了设置 ToolTip ,我再也没有错误了,但是其他的设置程序都没有任何效果——错误 日期选择器 看起来和以前一模一样。

    日期选择器 对于过去的某个日期,我在尝试调用时遇到堆栈溢出异常 DateTime.Now .

    通常,堆栈溢出异常会指示某种无限递归-事实上,当我在这行上设置断点时,它

    尽管如此,为什么会发生这种情况?你怎么能打电话来 是否可能导致对Validate方法的递归调用?为什么它只在我过去的约会中才这么做?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Richardissimo    7 年前

    您正在将日期选择器的SelectedDate属性绑定到其自身(这可能是导致堆栈溢出的原因……)

    WPF通常使用MVVM完成,其中绑定值位于ViewModel上,请尝试。

        2
  •  1
  •   Cinchoo    7 年前

    <Binding RelativeSource="{RelativeSource Self}" Path="SelectedDate">
    

    否则,您可以重新调整现有属性的用途,如下面的“标记”,以使其正常工作

    <Binding RelativeSource="{RelativeSource Self}" Path="Tag">
    

    希望这有帮助。