@@ -25,8 +25,9 @@ public class TimePicker : Control
25
25
private Popup _popup ;
26
26
private Button _dropDownButton ;
27
27
private bool _disablePopupReopen ;
28
+ private DateTime ? _lastValidTime ;
28
29
29
- static TimePicker ( )
30
+ static TimePicker ( )
30
31
{
31
32
DefaultStyleKeyProperty . OverrideMetadata ( typeof ( TimePicker ) , new FrameworkPropertyMetadata ( typeof ( TimePicker ) ) ) ;
32
33
}
@@ -67,10 +68,11 @@ public string Text
67
68
private static void SelectedTimePropertyChangedCallback ( DependencyObject dependencyObject , DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs )
68
69
{
69
70
var timePicker = ( TimePicker ) dependencyObject ;
70
- timePicker . SetCurrentValue ( TextProperty , timePicker . DateTimeToString ( timePicker . SelectedTime ) ) ;
71
- }
71
+ timePicker . SetCurrentValue ( TextProperty , timePicker . DateTimeToString ( timePicker . SelectedTime ) ) ;
72
+ timePicker . _lastValidTime = timePicker . SelectedTime ;
73
+ }
72
74
73
- public DateTime ? SelectedTime
75
+ public DateTime ? SelectedTime
74
76
{
75
77
get { return ( DateTime ? ) GetValue ( SelectedTimeProperty ) ; }
76
78
set { SetValue ( SelectedTimeProperty , value ) ; }
@@ -212,10 +214,36 @@ public override void OnApplyTemplate()
212
214
213
215
private void TextBoxOnLostFocus ( object sender , RoutedEventArgs routedEventArgs )
214
216
{
215
- SetSelectedTime ( ) ;
216
- }
217
+ if ( _textBox == null ) return ;
218
+
219
+ if ( ! string . IsNullOrEmpty ( _textBox . Text ) )
220
+ {
221
+ DateTime time ;
222
+ if ( IsTimeValid ( _textBox . Text , out time ) )
223
+ SetCurrentValue ( SelectedTimeProperty , time ) ;
224
+
225
+ else // Invalid time, jump back to previous good time
226
+ SetInvalidTime ( ) ;
227
+ }
228
+ }
229
+
230
+ private void SetInvalidTime ( )
231
+ {
232
+ if ( _lastValidTime != null )
233
+ {
234
+ SetCurrentValue ( SelectedTimeProperty , ( DateTime ) _lastValidTime ) ;
235
+ _textBox . Text = SelectedTime . Value . ToString ( SelectedTime . Value . Hour % 12 > 9 ? "hh:mm tt" : "h:mm tt" ) ;
236
+ }
237
+
238
+ else
239
+ {
240
+ SetCurrentValue ( SelectedTimeProperty , null ) ;
241
+ _textBox . Text = "" ;
242
+ }
217
243
218
- private void TextBoxOnKeyDown ( object sender , KeyEventArgs keyEventArgs )
244
+ }
245
+
246
+ private void TextBoxOnKeyDown ( object sender , KeyEventArgs keyEventArgs )
219
247
{
220
248
keyEventArgs . Handled = ProcessKey ( keyEventArgs ) || keyEventArgs . Handled ;
221
249
}
@@ -255,8 +283,9 @@ private bool ProcessKey(KeyEventArgs keyEventArgs)
255
283
256
284
private void TextBoxOnTextChanged ( object sender , TextChangedEventArgs textChangedEventArgs )
257
285
{
258
- SetCurrentValue ( TextProperty , _textBox . Text ) ;
259
- }
286
+ if ( _popup ? . IsOpen == true )
287
+ SetCurrentValue ( TextProperty , _textBox . Text ) ;
288
+ }
260
289
261
290
private void SetSelectedTime ( )
262
291
{
@@ -268,18 +297,24 @@ private void SetSelectedTime()
268
297
}
269
298
}
270
299
271
- private static void ParseTime ( string s , Action < DateTime > successContinuation )
300
+ private void ParseTime ( string s , Action < DateTime > successContinuation )
272
301
{
273
302
var dtfi = CultureInfo . CurrentCulture . GetDateFormat ( ) ;
274
303
275
304
DateTime time ;
276
- if ( DateTime . TryParseExact (
277
- s , new [ ] { dtfi . ShortTimePattern , dtfi . LongTimePattern } ,
278
- CultureInfo . CurrentCulture , DateTimeStyles . None , out time ) )
305
+ if ( IsTimeValid ( s , out time ) )
279
306
successContinuation ( time ) ;
280
307
}
281
308
282
- private string DateTimeToString ( DateTime ? d )
309
+ private bool IsTimeValid ( string s , out DateTime time )
310
+ {
311
+ return DateTime . TryParse ( s ,
312
+ CultureInfo . CurrentCulture ,
313
+ DateTimeStyles . AssumeLocal | DateTimeStyles . AllowWhiteSpaces ,
314
+ out time ) ;
315
+ }
316
+
317
+ private string DateTimeToString ( DateTime ? d )
283
318
{
284
319
return d . HasValue ? DateTimeToString ( d . Value ) : null ;
285
320
}
0 commit comments