0

I'm creating a wpf UserControl that contains a Datepicker. This datepicker is generated from code behind in c#.

public partial class EditorDatePicker : UserControl
{
    public EditorDatePicker(TagEntry element, bool isTagPresent)
    {
        InitializeComponent();

        // datepicker binding and validation
        Binding binding = new Binding();

        binding.Path = new PropertyPath("DateDict[" + element.ParentTag + element.ChildTag + "]");
        binding.NotifyOnValidationError = true;
        binding.ValidatesOnDataErrors = true;
        binding.Converter = new DateTimeConverter();
        binding.Mode = BindingMode.TwoWay;
        binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        binding.ValidationRules.Add(new DateValidationRule());

        this.datePicker.SetBinding(DatePicker.SelectedDateProperty, binding);
    }


class DateTimeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {

        if (value != null)
        {
            try
            {
                DateTime test = (DateTime)value;
                string date = test.ToString("d/M/yyyy");
                return (date);
            }
            catch
            {
                return null;
            }
        }
        return null;
    }

The fact is that the validation rule is never called when I manualy enter a date in the DatePicker text field (But it's called when using the datepicker). The only thing I got is a FormatException on lost focus.

Any idea? Thanx.

Fred B
  • 142
  • 1
  • 8
  • Validation runs after converter. You didn't specify any, so default behavior apply where entered `string` is converted into `DateTime`, producing `FormatException` if it's not possible. You can override binding exception filter if you want to customize (localize?) formatting error message or you have to supply custom converter. – Sinatr May 04 '17 at 12:24
  • Thanks Sinatr. I have tried to add a Converter. But it's only called when the View is loaded and not when I type into the datepicker's textbox. – Fred B May 04 '17 at 12:50
  • If you formulate what you are trying to achieve (what would that rule do), then I could give it a try. See [this](http://stackoverflow.com/q/6424074/1997232), maybe you run into similar to [this](http://stackoverflow.com/q/6363883/1997232) issue. – Sinatr May 04 '17 at 12:59
  • I've tried to convert the input value to DateTime, or return null if the conversion is not possible. I think my problem is that the Converter I set is only called when the view is loaded and not afterward. – Fred B May 04 '17 at 13:03
  • Are you binding to `DateTime?` property? `DateTime` is a struct (value type) it can't accept `null`. – Sinatr May 04 '17 at 13:05
  • I'm binding to `DateTime?`. – Fred B May 04 '17 at 13:08

1 Answers1

0

One possibility is to use converter:

public class DateTimeNullConverter : MarkupExtension, IValueConverter
{
    public override object ProvideValue(IServiceProvider serviceProvider) => this;

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is DateTime)
            return value.ToString();
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var text = value as string;
        DateTime result;
        if (text != null && DateTime.TryParse(text, out result))
            return result;
        return null;
    }
}

You can use it like this to bind to public DateTime? DateTime property:

<TextBox Text="{Binding DateTime, Converter={local:DateTimeNullConverter}}" />

ConvertBack will be called on lost focus.

Sinatr
  • 20,892
  • 15
  • 90
  • 319