WPF bound DatePicker not updating source - wpf

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

Related

DatePicker WPF + accepting dd/mm/yyyy format [duplicate]

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}}"
/>

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.

WPF ComboBox MVVM strange behavior

I'm having a strange behavior when I associate and combobox to my viewmodel. The behavior is the following, when I change the selected value of the combo I do a validation of the new value and if this new value is invalid I keep the old value and discard the new one, in this way I don't raise the Inotifypropertychanged, but the getter from the property associated to the combobox is call anyway, this gets the old value that I want to show, but instead the combobox shows the new value, even though the selectedvalue of the combo as the old and correct value, I checked in debug mode. I don't know how can I solve this because I never saw this kind of behavior, any suggestions would be much appreciated.
This is the code of the XAML
<ComboBox Height="23" Name="cbxStatus" HorizontalAlignment="Left"
ItemsSource="{Binding Path=Status, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=SelectedStatus, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Value" Width="130" VerticalAlignment="Center"
IsEnabled="{Binding Path=StatusEnable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
this is the viewmodel code, the property
public Config SelectedStatus
{
get
{
if (ApplicationAction == ApplicationAction.Add)
{
base.Object.State = configManager.BudgetInitStatus();
StatusEnable = false;
}
else
{
StatusEnable = true;
}
return base.Object.State;
}
set
{
if (base.Service.CanChangeBudgetStatus(base.Object, value))
{
base.Object.State = value;
base.Object.IsDirty = true;
}
RaiseOnPropertyChanged("SelectedStatus");
RaiseOnPropertyChanged("AssociateOrderButtonVisibility");
}
}
Thanks for the help
As indicated in my comment to Jay, the problem here is that WPF is setting the value and not listening to your change notification (which it is, after all, expecting). What you need to do is raise the property change notification outside the context of the current message. You could do this using the dispatcher, for example:
set
{
if (!valid)
{
// value is unchanged
Dispatcher.BeginInvoke(delegate { this.OnPropertyChanged(...) });
return;
}
// value is changed here
}
This will ensure the current data binding message is executed, then a separate message tells WPF that, "actually, the value you just provided to my setter is no longer the current value".
You could also use SynchronizationContext if you prefer. Either way, I admit it's a little hacky. Unfortunately, I don't know of a nice way around this. The fact is, WPF assumes that the value it passes to your setter is the effective value of the property. No amount of property change notifications within the context of the binding operation will convince it otherwise.
Setting your binding to
IsAsync=True
will work.
When the user changes the value in the combobox, it gets changed in the combobox, irrespective of your viewmodel.
If you change that value back and do not raise a property change notification, your viewmodel and view will be out of sync.
In short, when you reject the selected value you still need the property change notification.

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.

WPF DateTimePicker not setting date after validation

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.

Resources