Simplified Question:
I have a datepicker in WPF. I enter a value 30/10/1983 in the textbox of the datepicker. I need the value to be posted back to my viewmodel, where in I have bound it to a DateTime? property.
Is there any way I can achieve this. mm/dd/yyyy format triggers a postback but not dd/mm/yyyy.
The DatePicker code is as below.
<DatePicker Grid.Row="2" Name="inputDate"
Text="{Binding BirthDate,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
>
</DatePicker>
The view model property is as below.
private DateTime? birthDate;
public DateTime? BirthDate
{
get
{
return this.birthDate;
}
set
{
this.birthDate = value;
OnPropertyChanged("BirthDate");
}
}
I enter a value 10/10 into the datepicker textbox, the setter gets called with a value, but the moment I enter an entire date 30/10/1983, I still have the view model property which is equal to NULL.
I have changed the Format to English-UnitedKingdom, in the calendar settings, and my CurrentCulture reflects en-GB appropriately.
Original Question:
I have a datetimepicker control in WPF, which I have bound the text property to a Nullable DateTime in the view model.
The problem I am facing is when I enter a value in the format MM/dd/yyyy, I do get a value postback in the view model, indicating the new value.
But when I enter the value in dd/MM/yyyy format, I do not get a notification in the view model and the value is lost. The bound propertyin the view model is null.
The short date format is the one which I have specified in the calendar settings & dateFormat, within which for a short date format I provide the entry as "dd/MM/yyyy".
Could someone please help me with this scenario where in I accept date in dd/MM/yyyy format, and I do not want to hardcode, I wish to pick up the short date format from the calendar settings and also, I wish to recieve the updated value in the view model too.
The problem is related that a not valid date will not set with a correct value your ViewModel DateTime property. So, you can intercept it and convert correctly with a CONVERTER.
An example:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string strValue = System.Convert.ToString(value);
DateTime resultDateTime;
if (DateTime.TryParse(strValue, out resultDateTime))
{
return resultDateTime;
}
return value;
}
And your XAML code will be like:
<DatePicker
Text="{Binding BirthDate,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectedDate="{Binding RelativeSource={RelativeSource Self},Path=Text,
Converter={StaticResource DateConverter}}"
/>
Related
I am programming in WPF and in having an interface where Manufacturing date and Expiry date are two date pickers. How can I set my expiry date Date picker to select date only greater then mfg date?
The WPF datepicker doesn't have a minimum date property unfortunately, although it does have a DisplayDateStart dependency property. Within the calendar pop-up part of a datepicker control, this property hides dates prior to the assigned value.
However, users will be still be able to enter any expiry date using the textbox part of the datepicker. In order to handle this, you'll need to validate the SelectedDate properties of both datepickers.
I've attached code which does both (for the purpose of this question, I have assumed you're not using MVVM - if you are let me know):
Firstly, in XAML, the DisplayDateStart dependency property of the expiry datepicker is bound to the SelectedDate dependency property of the manufacturing datepicker (thus hiding invalid dates in the expiry datepicker calendar pop-up). As your requirement states "only greater than mfg date" a value converter is required to return the day after the manufacturing day.
<StackPanel>
<StackPanel.Resources>
<yournamespace:NextDayConverter x:Key="NextDayConverter" />
</StackPanel.Resources>
<DatePicker x:Name="ManufacturingDatePicker"
SelectedDateChanged="OnSelectedDateChanged" />
<DatePicker x:Name="ExpiryDatePicker"
SelectedDateChanged="OnSelectedDateChanged"
DisplayDateStart="{Binding
ElementName=ManufacturingDatePicker,
Path=SelectedDate,
Converter={StaticResource NextDayConverter}}" />
</StackPanel>
The NextDayConverter is detailed below:
namespace YourNamespace
{
using System;
using System.Globalization;
using System.Windows.Data;
public sealed class NextDayConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
DateTime manufacturingDate = (DateTime)value;
DateTime minimumExpiryDate = manufacturingDate.AddDays(1);
return minimumExpiryDate;
}
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Secondly, in code behind, there's a handler for the SelectedDateChanged event of both datepickers. The validation code in here sets the expiry date to the manufacturing date if the user enters an invalid expiry date (i.e. prior or equal to the manufacturing date).
private void OnSelectedDateChanged(object sender, SelectionChangedEventArgs e)
{
if (ManufacturingDatePicker.SelectedDate.HasValue &&
ExpiryDatePicker.SelectedDate.HasValue &&
ExpiryDatePicker.SelectedDate <= ManufacturingDatePicker.SelectedDate)
{
ExpiryDatePicker.SelectedDate = ManufacturingDatePicker.SelectedDate.Value.AddDays(1);
}
}
I hope this helps.
In my View.xaml I have a DatePicker bound to ViewModel's Date property
<DatePicker SelectedDate="{Binding Path=Date, Mode=TwoWay, Converter={StaticResource IfNullDateConverter}}" />
When View.xaml shown "IfNullConverter" is used to convert default DateTime value "01.01.0001" to DateTime.Now, so DatePicker displays current date. But actually the SelectedDate property is not set. Why?
When I press Save button, the DatePicker value passed to ViewModel is still "01.01.0001".
Please help, what am I doing wrong? How do I update my source code to pass current date if the date is "01.01.0001"?
IfNullDateConverter
DateTime dateValue = (DateTime)value;
if (dateValue.ToShortDateString() == "01.01.0001")
{
return DateTime.Now;
}
else
{
return value;
}
This is the right behavior. You should use converter when you want to convert the source value( Date in VM) and then set desdination(SelectedDate) with the new value. Which means that when you convert the source value, the result doesnt affect it, just the destination.
Conclusion : if you want to set a default value DateTime.Now to your property, you should do it in your VM
I have a form with a datepicker and a timepicker which both are bound to the same property from the model
here my simple Model:
private DateTime _end;
[Required]
public DateTime End
{
get
{
return _end;
}
set
{
_end = value;
RaisePropertyChanged(() => End);
}
}
the viewmodel has a property of the ModelObject.
My XAML looks like this
<sdk:DatePicker SelectedDate="{Binding Path=CurrentAppointment.End, Mode=TwoWay}"/>
<toolkit:TimePicker Value="{Binding Path=CurrentAppointment.End, Mode=TwoWay}" />
is there a simple way to precent the time from changing when i pick the date (it always goes back to 00:00 because the datepicker sets the date to 2011-04-29 00:00:00) or do i have to make a property for the time in my model and put the date and the time together when i want to put it in my database?
This question is exactly the same as
Using silverlight datepicker and timepicker together
Use Converter
You could either decide not to use data-binding and implement your logic with events, or you could use a converter and bind its parameter to the TimePicker. When you change the date, you can parse the parameter and attach it to the datetime.
I'm trying to validate the selected date in a datetime picker control and setting it to today's date if the date selected is > Datetime.Today.The issue I'm facing is that I'm not able to set the SelectedDate property of a datetimepicker control via xaml.I feel something is wrong with my binding, please can you help?
Following is the code.Please can you tell me what 'am I doing wrong?
<Controls:DatePicker Height="20"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
x:Name="dateControl"
IsTodayHighlighted="True"
Margin="5,10,5,20"
SelectedDate="{Binding Path=BindingDate, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
public class Context : INotifyPropertyChanged
{
public Context() { }
private DateTime bindingDate = DateTime.Today;
public DateTime BindingDate
{
get
{
return bindingDate;
}
set
{
if (DateTime.Compare(DateTime.Today, value) < 0)
{
MessageBox.Show("Please Select Today date or older, Should not select future date");
//This is not reflected anytime in SelectedDate property of the control, why???
value = DateTime.Today;
}
bindingDate = value;
OnPropertyChanged("BindingDate");
}
}
..and yes I'm setting the datacontext of the window like the following:
public Window1()
{
InitializeComponent();
this.DataContext = new Context();
}
Any suggestions would be highly appreciated.
Thanks,
-Mike
That is because the BindingDate setter will never be called if you set value for your local variable bindingDate and your ui will never be notified.
Instead of setting
private DateTime bindingDate = DateTime.Today.AddDays(13);
try setting
BindingDate = DateTime.Today.AddDays(13);
EDIT
But selecting a future date in the datepicker will remain even after showing the messagebox because the selection is already made in the control and will not reset back.
But you can consider other alternatives like blocking all future dates from selection by using the BlackoutDates or DisplayDates property of the datepicker or you can conside using custom validation rules as mentioned in the below post
Date picker validation WPF
You could consider implementing INotifyPropertyChanging also, and not only INotifyPropertyChanged.
In that way you can alsol notify that your property is about to change, and run some code accordingly.
And of course notify that your property has effectively changed.
I'm using the Silverlight DatePicker and TimePicker from the toolkit together to allow a user to select a date and time. They are bound to the same DateTime value on a business object behind the scences. This mostly works okay, except when the date component is changed the time component is wiped. This is kinda logical but probably not the behaviour the user wanted.
There's a couple of ways I could hack my way round this:
Store the date and time components in different values (not that hacky but a little anonying as I'm going to store the resulting value as one field in a db)
Try and fix up the time component when the SelectedDateChanged event fires (which does seem a very hacky solution)
I'd like to be able to tell the DatePicker control: just leave the time component when you change date. Am I hoping for too much?
I think, you can say DatePicker "Just leave the time component when you change date" using converter :). When you are binding DateTime to DatePicker converter stores value, and on ConvertBack returns without changes in Time part.
public class DateConverter : IValueConverter
{
private DateTime _original;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
_original = (DateTime)value;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
DateTime date = ((DateTime) value);
return new DateTime(date.Year, date.Month, date.Day, _original.Hour, _original.Minute, _original.Second);
}
}
XAML:
<sdk:DatePicker SelectedDate="{Binding Date, Mode=TwoWay,
Converter={StaticResource dateConverter}}" />
<input:TimePicker Value="{Binding Date, Mode=TwoWay}"/>