绑定到WPF中的ValidationRule

时间:2016-03-23 19:20:27

标签: wpf datetime mvvm data-binding validationrule

我是WPF的新手。表单的数据上下文包括StartTimeEndTime字段(使用MVVM),我已成功绑定到自己的文本框。我正在尝试创建验证,以检查新用户输入的StartTime是否在EndTime值之前。以下代码似乎不会将EndTime字段绑定到验证参数Maximum

XAML:

<TextBox>
    <TextBox.Text>
        <Binding Path="StartTime" UpdateSourceTrigger="LostFocus" StringFormat="{}{0:hh}:{0:mm}">
            <Binding.ValidationRules>                                            
                <local:ValidateTime>
                    <local:ValidateTime.Maximum>
                        <local:ValidationParameter Parameter="{Binding EndTime, StringFormat=hh\\:mm}" />
                    </local:ValidateTime.Maximum>
                </local:ValidateTime>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

查看型号:

public class ValidationParameter : DependencyObject
{
    public static readonly DependencyProperty ParameterProperty = DependencyProperty.Register(
        "Parameter",
        typeof(string),
        typeof(ValidationParameter),
        new FrameworkPropertyMetadata(null));

    public string Parameter
    {
        get { return (string)GetValue(ParameterProperty); }
        set { SetValue(ParameterProperty, value); }
    }
}

public class ValidateTime : ValidationRule
{
    private TimeSpan _Minimum = new TimeSpan(0, 0, 0);
    private TimeSpan _Maximum = new TimeSpan(23, 59, 9);
    private ValidationParameter _MinimumProperty;
    private ValidationParameter _MaximumProperty;

    public ValidationParameter Minimum
    {
        get
        {
            return _MinimumProperty;
        }
        set
        {
            TimeSpan ts;
            if (TimeSpan.TryParse(value.Parameter, out ts))
            {
                _Minimum = ts;
                _MinimumProperty = value;
            }
        }
    }

    public ValidationParameter Maximum
    {
        get 
        {
            return _MaximumProperty;
        }
        set 
        {
            TimeSpan ts;
            if (TimeSpan.TryParse(value.Parameter, out ts))
            {
                _Maximum = ts;
                _MaximumProperty = value;
            }
        }
    }

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
        string formattedValue = value.ToString();
        if (Regex.IsMatch(formattedValue, @"^\d{4}$"))
        {
            formattedValue = string.Format("{0}:{1}", formattedValue.Substring(0, 2), formattedValue.Substring(2, 2));
        }
        TimeSpan convertedValue;
        if (TimeSpan.TryParseExact(formattedValue, "g", System.Globalization.CultureInfo.CurrentCulture, out convertedValue))
        {
            if (convertedValue > _Maximum)
            {
                return new ValidationResult(false, string.Format("Time must be before {0}.", _Maximum.ToString("g")));
            }
            else if (convertedValue < _Minimum)
            {
                return new ValidationResult(false, string.Format("Time must be after {0}.", _Minimum.ToString("g")));
            }
            return ValidationResult.ValidResult;
        }
        else
        {
            return new ValidationResult(false, string.Format("'{0}' is not a valid time entry.", value.ToString()));
        }
    }
}

如果我将参数设置为如下所示的静态值,则代码可以工作,但我需要将此验证设置为动态:

<local:ValidateTime.Maximum>
    <local:ValidationParameter Parameter="12:00" />
</local:ValidateTime.Maximum>

3 个答案:

答案 0 :(得分:0)

首先,您要为TextBox命名,如下所示:

<TextBox Name="StartTime"/>

然后设置验证参数,如下所示:

<local:ValidateTime.Maximum>
    <local:ValidationParameter Parameter="{Binding ElementName=StartTime, Path=Text" />
</local:ValidateTime.Maximum>

如果验证工作就像你说的那样你应该全部设定。

如果您想要为其编写工作规则,您可以使用EndTime TextBox执行相同的操作

答案 1 :(得分:0)

您可能需要work around ValidationRules不在视觉或逻辑树中的事实,这会导致绑定到DataContextElementNameRelativeSource失败。

答案 2 :(得分:0)

就我而言

<local:RangeValidation ValidationStep="UpdatedValue"/>

帮助。因此,您将DependencyObject作为值(.dataitem)传递,包括您的Datacontext,并且无需将参数传递给Validation。 BR, 丹尼尔

顺便说一下BTW不是为了我,只是找到它但不记得是谁给了提示:)