你可以用DatePicker中的不同TextBox替换DatePickerTextBox并仍然获得验证功能吗?

时间:2014-06-04 17:56:22

标签: wpf validation datepicker controltemplate

我替换了DatePickerTextBox控件模板中的DatePicker,它不再确保输入文本的有效日期值。我也使用普通DatePickerTextBox测试了不同的字符串,并且没有验证它们,因此它必须是DatePickerTextBoxDatePicker之间的某种互动。有没有办法在控件模板中使用不是TextBox的不同DatePickerTextBox控件进行交互,还是必须在自己的自定义控件中重新创建验证?

1 个答案:

答案 0 :(得分:0)

答案的简短解释:

在自定义OnApplyTemplate控件的TextBox方法中,我添加了:

public override void OnApplyTemplate()
{
    LostFocus += OnLostFocus;

    base.OnApplyTemplate();
}

然后方法:

private void OnLostFocus(object sender, RoutedEventArgs e)
{
    if (!Text.Equals(oldText))
    {
        DateTime d;
        if (!DateTime.TryParse(Text, out d))
        {
            Text = oldText;
        }
    }
    oldText = Text;
}

如果您更换 DatePickerTextBox

我在reference source中探索并发现了以下内容:

OnApplyTemplate的{​​{1}}方法中,添加了一些处理程序,专门用于DatePicker,如果找不到,则不会应用它(这解释了原因) DatePickerTextBox无法自行验证,DatePickerTextBox添加处理程序,而不是DatePicker):

DatePickerTextBox

所以,追踪它(这是有趣的部分)......

_textBox = GetTemplateChild(ElementTextBox) as DatePickerTextBox;

if (this.SelectedDate == null)
{
    SetWaterMarkText();
}

if (_textBox != null)
{
    _textBox.AddHandler(TextBox.KeyDownEvent, new KeyEventHandler(TextBox_KeyDown), true);
    _textBox.AddHandler(TextBox.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged), true);
    _textBox.AddHandler(TextBox.LostFocusEvent, new RoutedEventHandler(TextBox_LostFocus), true);

    if (this.SelectedDate == null)
    {
        if (!string.IsNullOrEmpty(this._defaultText))
        {
            _textBox.Text = this._defaultText;
            SetSelectedDate();
        }
    }
    else
    {
        _textBox.Text = this.DateTimeToString((DateTime)this.SelectedDate);
    }
}

然后:

private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
    SetSelectedDate();
}

重要的是调用private void SetSelectedDate() { if (this._textBox != null) { if (!string.IsNullOrEmpty(this._textBox.Text)) { string s = this._textBox.Text; if (this.SelectedDate != null) { // If the string value of the SelectedDate and the TextBox string value are equal, // we do not parse the string again // if we do an extra parse, we lose data in M/d/yy format // ex: SelectedDate = DateTime(1008,12,19) but when "12/19/08" is parsed it is interpreted as DateTime(2008,12,19) string selectedDate = DateTimeToString(this.SelectedDate.Value); if (string.Compare(selectedDate, s, StringComparison.Ordinal) == 0) { return; } } DateTime? d = SetTextBoxValue(s); if (!this.SelectedDate.Equals(d)) { this.SetCurrentValueInternal(SelectedDateProperty, d); this.SetCurrentValueInternal(DisplayDateProperty, d); } } else { if (this.SelectedDate.HasValue) { this.SetCurrentValueInternal(SelectedDateProperty, (DateTime?)null); } } } else { DateTime? d = SetTextBoxValue(_defaultText); if (!this.SelectedDate.Equals(d)) { this.SetCurrentValueInternal(SelectedDateProperty, d); } } }

SetTextBoxValue

重要的是调用private DateTime? SetTextBoxValue(string s) { if (string.IsNullOrEmpty(s)) { SafeSetText(s); return this.SelectedDate; } else { DateTime? d = ParseText(s); if (d != null) { SafeSetText(this.DateTimeToString((DateTime)d)); return d; } else { // If parse error: // TextBox should have the latest valid selecteddate value: if (this.SelectedDate != null) { string newtext = this.DateTimeToString((DateTime)this.SelectedDate); SafeSetText(newtext); return this.SelectedDate; } else { SetWaterMarkText(); return null; } } } }

ParseText

最后两种方法都有我正在寻找的验证。如果private DateTime? ParseText(string text) { DateTime newSelectedDate; // TryParse is not used in order to be able to pass the exception to the TextParseError event try { newSelectedDate = DateTime.Parse(text, DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this))); if (Calendar.IsValidDateSelection(this._calendar, newSelectedDate)) { return newSelectedDate; } else { DatePickerDateValidationErrorEventArgs dateValidationError = new DatePickerDateValidationErrorEventArgs(new ArgumentOutOfRangeException("text", SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue)), text); OnDateValidationError(dateValidationError); if (dateValidationError.ThrowException) { throw dateValidationError.Exception; } } } catch (FormatException ex) { DatePickerDateValidationErrorEventArgs textParseError = new DatePickerDateValidationErrorEventArgs(ex, text); OnDateValidationError(textParseError); if (textParseError.ThrowException && textParseError.Exception != null) { throw textParseError.Exception; } } return null; } 返回ParseText,则null会将文本框中的值恢复为之前的值。由于SetTextBoxValue是添加处理程序的控件,因此您无法在DatePicker之外获得验证。由于DatePicker专门针对名为DatePicker的{​​{1}}(DatePickerTextBox字符串是什么),因此必须使用"PART_TextBox",否则处理程序不会应用(因为ElementTextBox将是DatePickerTextBox)。