首页 > 解决方案 > 验证字段后,属性具有最后一个有效值

问题描述

在我的 WPF 项目中,我开始使用带有文本字段的 ValidationRule 并发现了一个问题。我创建了一个简单的项目来测试 ValidationRule。一切正常,但如果我的输入值不在有效范围内,我的属性将存储最后一个有效值。这就是为什么我有一个问题:如何检查对ValidationRule无效的当前值?可能是,我做错了什么?

主窗口

</Window ... >
  <Window.Resources>
        <ControlTemplate x:Key="errorTemplate">
            <Border BorderBrush="OrangeRed" BorderThickness="2">
                <Grid>
                    <AdornedElementPlaceholder/>
                    <TextBlock Text="{Binding [0].ErrorContent}" Foreground="OrangeRed"
                               VerticalAlignment="Center" HorizontalAlignment="Right"
                               Margin="0,0,4,0"/>
                </Grid>
            </Border>
        </ControlTemplate>
    </Window.Resources>

    <StackPanel>
        <TextBox Validation.ErrorTemplate ="{StaticResource errorTemplate}"
                 HorizontalAlignment="Center" VerticalAlignment="Center"
                 Width="200" Margin="0 20">          
                <TextBox.Text>
                <Binding Path="ForText" 
                         UpdateSourceTrigger="PropertyChanged">
                        <Binding.ValidationRules>
                            <local:EmptyFieldRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>           
        </TextBox>
        <Button Content="Check"
                Command="{Binding ForCommand}"
                 HorizontalAlignment="Center"
                 VerticalAlignment="Center"
                Width="40"/>
    </StackPanel>
</Window>

我在 DataContext 中设置的 Window 视图模型:

public class MainWindowVM : VM
    {
        private string _text = "some text";
        public string ForText
        {
            get => _text;
            set { _text = value; OnPropertyChanged(nameof(ForText)); }
        }
        public ICommand ForCommand { get; set; }
        public MainWindowVM() { ForCommand = new RelayCommand(() => MessageBox.Show(ForText)); }
    }

验证规则:

public class EmptyFieldRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            string information = value as string;
            if (string.IsNullOrWhiteSpace(information))
                return new ValidationResult(false, "!!!");

            return ValidationResult.ValidResult;
        }
    }

标签: c#wpfxaml

解决方案


Binding在 wpf 中,ValidationRule在更新值之前评估所有值。您必须在EmptyFieldRule类中进行一些更改才能实现此目的。这是解决您的问题的一种技巧,但还有其他更好的方法来实现相同的。

ValidationStep将属性更改为ValidationStep.UpdatedValue并用于Reflection获取ValidationResult方法中的更新值。

public class EmptyFieldRule : ValidationRule
{
    public EmptyFieldRule()
    {
        this.ValidationStep = ValidationStep.UpdatedValue;
    }
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var expression = value as BindingExpression;
        var information = expression?.DataItem?.GetType()?.GetProperty(expression.ResolvedSourcePropertyName)?.GetValue(expression.DataItem) as string;
        if (string.IsNullOrWhiteSpace(information))
            return new ValidationResult(false, "!!!");

        return ValidationResult.ValidResult;
    }
}

推荐阅读