tags:

views:

490

answers:

2

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
        }
    }
+1  A: 

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.

Josh G
In this case, the backing data property is always setting the value of a DependencyProperty (this is used in a custom control) using SetValue. I added the code above. And just to make sure, I called OnPropertyChanged afterwards too - no change! Rats!
Scott O.
Sorry, I didn't realized you were using a dependency property on the source. That makes this answer irrelevant.
Josh G
A: 

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!

Scott O.