如何在datepicker格式上禁用自动完成功能

时间:2017-05-12 09:19:34

标签: c# wpf autocomplete datepicker

我有一个日期选择器,它有一个控制模板来设置文本框中显示的日期的字符串格式

<DatePicker x:Name="CustomDatePicker" BorderBrush="LightGray">
    <DatePicker.Resources>
        <Style TargetType="{x:Type DatePickerTextBox}">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBox x:Name="PART_TextBox"
                        Text="{Binding Path=SelectedDate, RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}, StringFormat={}{0:dd/MM/yyyy}, TargetNullValue=''}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DatePicker.Resources>
</DatePicker>

除非用户尝试以文本方式修改日期,否则一切正常。

例如:

如果我们设置“01/01/201”,它将自动完成为“01/01/0201”(通过在开头添加0)

如果我们设置“01/01/9”,它将自动完成“01/01/2009”

所有这些都说这个自动完成功能不直观且可预测,所以我想禁用它。

如果用户放置了无效的日期格式(如果年份部分中没有4位数字),我宁愿显示错误...

感谢您的帮助

1 个答案:

答案 0 :(得分:1)

通过查看DatePicker源代码,看起来这种行为的真正原因是DateTime.Parse()方法被ParseText()用于转换为选定日期。

您可以通过扩展DatePicker控件并在文本到达ParseText()方法之前预先验证来覆盖此行为。

public class ExtendedDatePicker : DatePicker
{
    TextBox _textBox = null;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        //subscribe to preview-lost-focus event
        _textBox = GetTemplateChild("PART_TextBox") as DatePickerTextBox;
        _textBox.AddHandler(TextBox.PreviewLostKeyboardFocusEvent, new RoutedEventHandler(TextBox_PreviewLostFocus), true);
    }

    private void TextBox_PreviewLostFocus(object sender, RoutedEventArgs e)
    {
        ValdateText(_textBox.Text);
    }

    private void ValdateText(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return;

        // ---- Add/update your valid date-formats here ----
        string[] formats = { "dd/MM/yyyy", "dd/M/yyyy", "d/M/yyyy", "d/MM/yyyy",
                "MM/dd/yyyy", "M/dd/yyyy", "M/d/yyyy", "MM/d/yyyy"};

        CultureInfo culture = CultureInfo.InvariantCulture;
        DateTimeStyles styles = DateTimeStyles.None;
        DateTime temp;
        if (DateTime.TryParseExact(text, formats, culture, styles, out temp))
        { 
            //do nothing
        }
        else
        {
            //raise date-picker validation error event like ParseText does
            DatePickerDateValidationErrorEventArgs dateValidationError = 
                new DatePickerDateValidationErrorEventArgs(new FormatException("String was not recognized as a valid DateTime."), text);
            OnDateValidationError(dateValidationError);

            _textBox.Text = string.Empty; //suppress parsing in base control by emptying text
        }
    }
}