在WPF中,我有一个带有以下文本样式的日期选择器:
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox"
Text="{Binding Path=SelectedDate, StringFormat='dd/MM/yyyy',
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}"
Foreground="white"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
datepicker项目本身看起来像这样
<DatePicker x:Name="datepickShowDate" Grid.Column="1" Foreground="white" CalendarStyle="{StaticResource styleCalendar}"
FontSize="14" HorizontalAlignment="Left" Height="30"
VerticalAlignment="Top" Width="139"/>
如果我从弹出日历中选择日期,则日期显示正常。 但是,如果我输入日期,它似乎假设我以美国格式输入并转换为英国。
即。如果我想在2018年6月5日输入像05/06/2018一样,点击该字段时它突然变成06/05/2018。
我的问题是,有没有什么方法可以定义输入格式,而不仅仅是日期选择后的日期应该是什么样的?
答案 0 :(得分:2)
似乎StringFormat
不会影响从用户输入收到的值。
来自docs:
获取或设置一个字符串,指定如何格式化绑定 将绑定值显示为字符串。
我相信有更强大的解决方案,但如果不使用转换器,我找不到任何可以解决此问题的方法。
public class DateTimeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var dateTime = (DateTime?)value;
if (!dateTime.HasValue)
{
return string.Empty;
}
var format = (string)parameter;
return dateTime.Value.ToString(format, culture);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var format = (string)parameter;
DateTime dateTime;
if (DateTime.TryParseExact((string)value, format, culture, DateTimeStyles.None, out dateTime))
{
return dateTime;
}
return DependencyProperty.UnsetValue;
}
}
这里的技巧是在ConvertBack
方法中使用DateTime.TryParseExact
,将格式作为参数传递。
但是有一个缺点 - 你只能使用一种格式--dd / MM / yyyy。如果您输入类似2018-04-29的内容 - 它将无效。
要使用此转换器,您需要在资源中声明它:
<local:DateTimeConverter x:Key="converter"/>
并使用ConverterParameter
代替StringFormat
(尽管您可以使用StringFormat
,但会在应用转换器后使用它):
Text="{Binding Path=SelectedDate,
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}},
Converter={StaticResource converter},
ConverterParameter='dd/MM/yyyy'}"
答案 1 :(得分:1)
您可以创建自定义DatePicker
:
public class UkDatePicker : DatePicker
{
private DatePickerTextBox _datePickerTextBox;
private const string _shortDatePattern = "dd/MM/yyyy";
private readonly CultureInfo _formatProvider = new CultureInfo("en-GB");
public UkDatePicker()
{
Language = XmlLanguage.GetLanguage(_formatProvider.IetfLanguageTag);
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_datePickerTextBox = Template.FindName("PART_TextBox", this) as DatePickerTextBox;
if (_datePickerTextBox != null)
{
_datePickerTextBox.SetBinding(TextBox.TextProperty, new Binding(nameof(DatePicker.SelectedDate))
{
RelativeSource = new RelativeSource() { AncestorType = typeof(DatePicker) },
StringFormat = _shortDatePattern
});
_datePickerTextBox.TextChanged += dptb_TextChanged;
}
}
private void dptb_TextChanged(object sender, TextChangedEventArgs e)
{
DateTime dt;
if (DateTime.TryParseExact(_datePickerTextBox.Text, _shortDatePattern, _formatProvider,
DateTimeStyles.None, out dt))
{
SelectedDate = dt;
}
}
}
示例XAML:
<local:UkDatePicker DockPanel.Dock="Top" SelectedDate="{Binding Date}"/>
<StackPanel Orientation="Horizontal" Margin="0 10 0 0">
<TextBlock Text="Selected Date: " FontSize="16" FontWeight="Bold"/>
<TextBlock Text="{Binding Date, StringFormat=dd/MM/yyyy}" FontSize="16"/>
</StackPanel>
查看型号:
public class ViewModel : INotifyPropertyChanged
{
private DateTime? _date;
public DateTime? Date
{
get { return _date; }
set { _date = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}