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