Forcing Convert to always run when using custom converter in WPF?
Question
I'm implementing a custom date converter in WPF, the idea to be more clever about date entry, a la Outlook (being able to enter "today", etc.) So I've written my own converter, which is working. It formats the user's entry in the format M/d/yy. So for example, if they enter: 8-2, they'll see 8/2/09. Lovely.
The question is: there are several things the user can enter that ultimately result in the same date. (8-2 and 8/2, being easy examples). So let's just say they start off by entering 8/2, which gets run through ConvertBack and Convert, and gets displayed as 8/2/09. So far so good. Now let's say they enter 8-2 (or 8/2 again) in that same field, right afterwards. That gets run though ConvertBack, which yields the SAME date that's already there in the bound property, so it doesn't bother to run Convert, which means that that "8/2" is sitting there in the textbox. Yick! There's no data issue, just a display one, but hey, neatness counts.
How can I force WPF to run Convert after ALL (non-error) entries?
Here's a simplified version of the converter:
public class DateConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value != null)
{
string tempStr = value.ToString();
return ((DateTime.Parse(tempStr)).ToString("M/d/yy"));
}
else
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return DateTime.Parse(value.ToString());
}
#endregion
}
and here's what the use of it looks like:
<local:FilteredTextBox.Text>
<Binding Path="Value" ElementName="root" Converter="{StaticResource DateConv}"
UpdateSourceTrigger="LostFocus" Mode="TwoWay" diagnostics:PresentationTraceSources.TraceLevel="High"
NotifyOnValidationError="True" ValidatesOnDataErrors="True" ValidatesOnExceptions="True">
<Binding.ValidationRules>
<local:DateValidation/>
</Binding.ValidationRules>
</Binding>
</local:FilteredTextBox.Text>
Thanks! Scott
In response to a comment below, here's the backing property:
public DateTime? Value
{
get
{
return (DateTime?)GetValue(ValueProperty);
}
set
{
SetValue(ValueProperty, value);
OnPropertyChanged(new DependencyPropertyChangedEventArgs(ValueProperty, null, value)); // I just added this line, it makes no difference
}
}
Solution 2
Many thanks to Josh G - with his help, I figured out the (or at least an) answer.
This was for a textbox within a DatePicker control I'm creating. So rather than "lock" the textbox directly to the value of the control, I created an intermediate property, which THEN calls the set to the dependency property:
public DateTime? DateValue
{
get
{
return _dateValue;
}
set
{
_dateValue = value;
OnPropertyChanged("DateValue");
SetValue(ValueProperty, _dateValue);
}
}
and this totally works as it should. Thanks again, Josh!
OTHER TIPS
Is it possible that the backing data property is only firing PropertyChanged
if it actually changes value? You could try firing PropertyChanged
whenever the set function is called regardless of whether the value changes. This would cause the binding to be updated.