WPF DateTimePicker not setting date after validation - wpf

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.

Related

WPF bound DatePicker not updating source

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

How to refresh binding data in silverlight mvvm using NotificationObject

i'm working on a textbox required TimeSpan value. the input content need to be validated and may in several different formats (for ex 1300 means 13:00). I do some work to check and convert it in viewmodel. but after that how can i refresh the text in textbox?
<TextBox Text="{Binding Path= OpenHourFromText, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" ></TextBox>
OpenHourFromValue is a string property that i used for validation and data binding
public class MainPageViewModel : NotificationObject{
public string OpenHourFromText
{
get
{
//OpenHourFrom is a TimeSpan property that contain the value
if (OpenHourFrom != null)
{
return GetOpeningHourText(OpenHourFrom); //fomat the time
}
else
{
return "";
}
}
set
{
//do validation and convert here. 1300 will be changed to 13:00 TimeSpan type
OpenHourFrom = ConvertToTimeSpan(value);
RaisePropertyChanged("OpenHourFromText");
}
}
public TimeSpan OpenHourFrom { get; set; }
}
the viewmodel is inherit from Microsoft.Practices.Prism.ViewModel.NotificationObject
After i input 1300 in the textbox, the OpenHourFrom is updated. But the text of textbox is not changed to 13:00. why? please help, many thx.
When TextBox is setting some value it won't call get.The solution to this can be like replacing RaisePropertyChanged("OpenHourFromText") with Dispatcher.BeginInvoke(() => RaisePropertyChanged("OpenHourFromText"));It will delay firing that event.
set
{
//do validation and convert here. 1300 will be changed to 13:00 TimeSpan type
OpenHourFrom = ConvertToTimeSpan(value);
Dispatcher.BeginInvoke(() => RaisePropertyChanged("OpenHourFromText"));
}
You're raising a PropertyChange notification for the property UpdateTimeText, while your actual property name is OpenHourFromText
Change your PropertyChange notification to raise the notification for the correct property, and it should update for you.

Silverlight control's input validation

I want to implement two types of validation in my silverlight application. I want "business-logic" rules to be implemented in viewmodel(like end date is not earlier than start date) which i have already accomplished, and input validation somewhere on main control, where input fields are(like date is in bad format). Is there anything silverlight can "help" me with? I mean there is at least UnsetValue there for me, but is there any event associated or i have to catch all OnChanged events? Also is there a way to manually display red border around control when i want to?
Sorry, it was not obvious from my question, but i finished with the part that includes "business-logic" rules - my viewmodel indeed implements INotifyDataErrorInfo, i'm troubled with second type of validation.
Implement INotifyDataErrorInfo on your ViewModel to enable validation on View Model level.
Implement INotifyDataErrorInfo on your properties
then on your property that is binded in XAML use a friendly display name:
private DateTime? _datumP = DateTime.Now;
[Display(Name = "Date", ResourceType = typeof(CommonExpressions))]
public DateTime? DatumP
{
get
{
return _datumP;
}
set
{
if (_datumP != value)
{
_datumP = value;
RaisePropertyChanged(DatumPonudbePropertyName);
}
ValidateDate(DatumPonudbe, DatumPonudbePropertyName);
}
}
Then your method to validate dates:
public void ValidateDate(DateTime? value, string propertyName)
{
RemoveError(propertyName, CommonErrors.DatumNull_ERROR);
if (value == null)
AddError(propertyName, CommonErrors.DatumNull_ERROR, false);
}
And now for the XAML part:
<sdk:DatePicker Width="100" SelectedDate="{Binding DatumP, Mode=TwoWay,
NotifyOnValidationError=True, ValidatesOnNotifyDataErrors=True,
ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" />
P.S.
CommonExpressions and CommonErrors are my Resource files for multilanguage, you can use plain strings here.

PropertyChangeCallBack not firing on DependencyProperty in a UserControl

Stumped : I am in the initial stages of creating a month planner control that need to carry out some UI action I The control when supplying a date from the ViewModel bound in XAML. When I run the code, the ViewModel does return the value but the PropertyChangeCallBack is not firing. I have done exactly the same thing in an public class ExtendedDataGrid : DataGrid control and that work fine but it is almost like you have to do something different with UserControls. Here is the basis of my code:
public partial class DiaryMonthViewUserControl : UserControl
{
private DateTime _topDate;
public DiaryMonthViewUserControl()
{
InitializeComponent();
}
// Property to get the date from the ViewModel for processing. This will fire and event to set the month we want to display
public static readonly DependencyProperty TheDateProperty = DependencyProperty.Register("TheDate", typeof(DateTime),
typeof(DiaryMonthViewUserControl),
new FrameworkPropertyMetadata(DateTime.Today, OnDatePropertyChanged, null));
public void SetTheCurrentDate(DateTime CurrentDate)
{
_topDate = CurrentDate;
// Like Outlook, whatever date we supply, I want the first top level displayed date for the month
if (_topDate.Day > 1)
_topDate = _topDate.AddDays(-(_topDate.Day-1)); // First day of the month
// Get to the first Monday before the 1st of the month if not on a Monday
while (_topDate.DayOfWeek != DayOfWeek.Monday)
_topDate = _topDate.AddDays(-1);
// I will set the UI here once I have solved this problem.
MakeChangesToTheUIPlease();
}
private static void OnDatePropertyChanged(DependencyObject Source, DependencyPropertyChangedEventArgs e)
{
var control = Source as DiaryMonthViewUserControl;
if (control != null)
control.SetTheCurrentDate((DateTime)e.NewValue);
}
[Bindable(true)]
public DateTime TheDate
{
get { return (DateTime)GetValue(TheDateProperty); }
set { SetValue(TheDateProperty, value); }
}
}
I have also tried using new PropertyChangedCallback(OnDatePropertyChanged) as a parameter and that still does not work.
My binding is as follows:
<my:DiaryMonthViewUserControl HorizontalAlignment="Left" Margin="12,12,0,0" x:Name="diaryMonthViewUserControl1"
VerticalAlignment="Top" Height="325" Width="476" TheDate="{Binding Path=CurrentDate}" />
When I run the code my ViewModel breaks on the getter for CurrentDate and if I remove the CurrentDate binding then it does not. The problem is that the call back is not firing and, for the life of me, I cannot fathom why.
Any help would be much appreciated, particularly links to articles that may cover this problem.
The PropertyChanged callback only fires if the immediate property is changed, that means the whole DateTime object would need to be replaced, if properties of the DateTime object are changed the event will not be raised. This is why it works for primitive types like int.
If you want to execute some method whenever any property of the DateTime changed you could implement a DateTime class which provides notifications. You can then execute the method whenever any of the properties change.

Datepicker updates Timepicker

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.

Resources