This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hi guys, We've recently purchased the Mindscape WPF controls, principly because of the DateTimePicker controls. There's a couple of things we'd like it to do that we just can't figure out though. When using the DateTimePicker and the DropDownDatePicker it's possible that the user could click in one of the numeric fields, clear the value, then change focus to another field in the control. In our situation it's not acceptable for that field to be left blank, as it it currently is. How do we retreive the previous value of the field when it looses focus and write it back in again? The other problem we have is that for the data we're working with we'll sometimes come across situations where we'd like to let the user use the DateTimePicker controls to *define* an undefined date if the data is missing, but if they choose not to define a date we'd like to leave the record alone. The problem is, when the DateTimePicker/DropDownDatePicker controls are created they have a default date of "DateTime.Now()" - when really we'd like the DateTime fields to be completely empty (so that the user doesn't get the idea that there is a valid date in the field). Ideally, the DropDownDatePicker calender should default to the current month when the drop-down arrow is clicked - but even then if nothing is selected by the user we'd like to leave the fields at the top empty. Again, do you know how we would achieve such behaviour? Regards, Martina
|
|
|
Hi Martina, Re resetting blank fields to the underlying value, we don't have a nice built-in method for doing that, but here's a trick you can use to make it happen. It's rather kludgy I'm afraid though. Handle the LostFocus event of the DateTimePicker. (Because LostFocus is a routed event, this fires as the user mouses or tabs between fields, not just when the user leaves the entire DateTimePicker.) In your event handler, retrieve the data binding of the Value property (assuming the control is data bound). Then clear the Value property (removing the binding), and then re-apply the binding: Binding binding = BindingOperations.GetBinding(dtp, DateTimePicker.ValueProperty); If you're not data bound, you can probably work a similar trick by getting the value using the normal CLR Value property, doing ClearValue() and then setting the value again using the CLR property (I haven't tested this though). Your other problem is a bit trickier because we don't currently have the concept of an "undefined" date. In fact it goes a bit further than that because we would probably need the concept of a "partially defined" date for when the user has entered, say, the day of the month, but not yet a month or year. Perhaps you could say a bit more about how you are representing this in the underlying data model and the interaction you would like to see around missing and partial entries, and we will see if we can come up with any good ideas. Thanks! |
|
|
Hi Ivan, for the case of re resetting blank fields i'm not databinded so i tried your second proposal using ClearValue(). I've build a sample project with the following codes. Sometimes it works but sometimes not. Have you any idea why? Kind regards Martina
XAML: < Window x:Class="MindscapeDateTimePickerEval.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ms="http://namespaces.mindscape.co.nz/wpf" xmlns:local="clr-namespace:Mindscape.WpfElements;assembly=Mindscape.WpfElements"Title="Window1" Height="300" Width="300"> <Grid> <StackPanel> <ms:DateTimePicker Name="timePicker" Format="LongTime" Width="100" Height="20" LostFocus="timePicker_LostFocus"/> <ms:DropDownDatePicker Name="datePicker" Format="ShortDate" Width="100" Height="20" LostFocus="datePicker_LostFocus" /> <ms:DropDownDatePicker Name="dateTimePicker" Format="Custom" LostFocus="dateTimePicker_LostFocus" /> </StackPanel></Grid> </ Window>
C#: using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;using System.Globalization;using Mindscape.WpfElements;namespace MindscapeDateTimePickerEval{ /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : Window{ public Window1(){ InitializeComponent(); CultureInfo cultInfo = System.Globalization.CultureInfo.CurrentCulture;dateTimePicker.CustomFormat = cultInfo.DateTimeFormat.ShortDatePattern + " " + cultInfo.DateTimeFormat.LongTimePattern;timePicker.Value = new DateTime(1500, 1, 1, 1, 1, 1);datePicker.Value = new DateTime(2008, 8, 20);dateTimePicker.Value = new DateTime(2008, 8, 20, 1, 1, 1);} private void dateTimePicker_LostFocus(object sender, RoutedEventArgs e){ DateTime value = (sender as DropDownDatePicker).Value;(sender as DropDownDatePicker).ClearValue(DropDownDatePicker.ValueProperty);(sender as DropDownDatePicker).Value = value;} private void datePicker_LostFocus(object sender, RoutedEventArgs e){ DateTime value = (sender as DropDownDatePicker).Value;(sender as DropDownDatePicker).ClearValue(DropDownDatePicker.ValueProperty);(sender as DropDownDatePicker).Value = value;} private void timePicker_LostFocus(object sender, RoutedEventArgs e){ DateTime value = (sender as DateTimePicker).Value;(sender as DateTimePicker).ClearValue(DateTimePicker.ValueProperty);(sender as DateTimePicker).Value = value;} } }
|
|
|
Hi Martina, I haven't been able to determine why this is misbehaving, but I do have a fix. It appears to work properly if you replace your ClearValue calls with explicitly setting the value to a dummy value (and then resetting it), e.g.: DateTime value = (sender as DropDownDatePicker).Value; Please note the following issues: 1. Changing the value in the LostFocus event confuses the drop-down calendar if it is in use. Therefore, you should execute the above code only if the LostFocus event is coming from outside the drop-down calendar. Here is some code you can use to determine this: private static bool IsWithinMonthCalendar(DependencyObject obj) And guard your value reset code as follows: if (!IsWithinMonthCalendar(e.OriginalSource as DependencyObject)) Sorry for this additional complexity; I hadn't originally realised you were using the drop-down control. 2. Do not use DateTime.MinValue or DateTime.MaxValue as your dummy value. We have a known bug around displaying these values in the drop-down calendar (and even though the user never sees the dummy value displayed, setting it to one of these values would still trigger this bug). 3. Setting the Value like this is appropriate only for unbound controls; do NOT do this if you are data binding because that will cause the dummy value to get propagated to the binding source, rather than clearing the binding! In the data binding scenario, you must use ClearValue. But setting the value to a dummy *is* okay if the control is not data bound. Please let me know if this workaround doesn't work for you. By the way, I noticed in your repro code that you are using a format that includes a time with the DropDownDatePicker. You need to be a little bit cautious about this. The reason for this is that if the user drops down the calendar and selects a date, this will be taken as the entire value of the control -- the time part will be reset (though the user can then edit the time to the desired value, as long as they don't drop the calendar down again). (We hope to improve this behaviour in a future release.) |
|
|
Hi Ivan, thanks for your quick answer and your additonal informations. Setting the Value Property to another Date instead of using the ClearValue() methods has the same effect. When i remove a part with the Del-Key and go to the next element sometimes the display is still empty. Mostly i can reproduce this behaviour in the display element of the year. In the display element for day, month, hour, minutes or seconds sometimes it has the same effect. Have you any other idea? Regards, Martina |
|
|
Which version of the framework are you using? I did my tests using .NET 3.5 SP1 (VS2008 SP1) and I found that with ClearValue() the year would always remain empty but with setting the Value property it worked reliably. In both cases, I never saw any problems with the day, month, hour, minutes or seconds. This difference in what you and I are seeing makes me wonder if this is due to some minor difference in behaviour between WPF versions (e.g. notifications from the dependency property system happening or being processed in a slightly different order). If you are not currently using 3.5 SP1, is upgrading to that version an option for you? |
|
|
I'm also using .NET 3.5 SP1 and VS2008 SP1. I found out that my problem only exists if i have in the year of the Value property for example 2008 and use in the LostFocus event also a date with the year 2008. For examlple: dateTimePicker.Value = new DateTime(2008, 5, 10); void dateTimePicker_LostFocus(object sender, RoutedEventArgs e){ DateTime orgValue = (sender as DateTimePicker).Value;(sender as DateTimePicker).Value = new DateTime(2008,1,1);(sender as DateTimePicker).Value = orgValue;} If i replace now the line (sender as DateTimePicker).Value = new DateTime(2008,1,1); with (sender as DateTimePicker).Value = new DateTime(1980,5,10); i have the problem in the month and day element. Otherwise it works fine. Any idea? |
|
|
Well, I'm still puzzled as to why it is behaving this way, and I have to admit that all I can give you right now is another workaround, but hopefully it will still be better than nothing... The workaround is, for your dummy date, to use a value that is guaranteed to be different in year, month and day from the current value. For example, add 400 years, 1 month and 1 day to the current value: DateTime value = (sender as DropDownDatePicker).Value; (The reason for adding 400 years rather than 1 year is to deal with the case where value is a February 29th. If we added 1 year, then Feb 29 would get mapped to Feb 28, and from there to March 29, meaning we'd hit the empty text bug in the day of month field. [Adding 4 years or 100 years will appear to work for dates around now, but will hit the same glitch if the user enters 29 Feb 2096 or 29 Feb 2000 respectively.] Adding 400 years guarantees that, if the original value was Feb 29, the result of the AddYears() call will also be Feb 29, which then maps to March 30, avoiding any clash.) You'll want to encapsulate all of this within an appropriately named method. Thanks for the detailed reporting and diagnosis of the problem; this will help us track down and fix the behaviour. In the meantime, I hope this workaround finally addresses it for you... |
|
|
This workaround works fine. Thanks for your help! |
|