Question

I am achieving a function "WPF Validation On StartDate and EndDate (StartDate less than Enddate)", I write code in code behind to throw an exception if the EndDate is less than the StartDate, and now it works. But I met a problem about the validation on StartDate and EndDate fileds. Since these two properties are compulsory fields in my database, the Save button should be disabled unless you fill these two fields. But now StartDate and EndDate fileds are not compulsory. I am attaching my codes. Can you please spare a few minutes to look at my code and provide some suggestions? Many thanks.

Code Behind

public partial class OrganisationTypeSView : UserControl
{

    OrganisationTypeViewModel _dataContext = new OrganisationTypeViewModel();
    public OrganisationTypeSView()
    {
        InitializeComponent();

     this.DataContext = _dataContext;

        _dataContext.AccountStartDate = DateTime.Now;
        _dataContext.AccountEndDate = DateTime.Now.AddMonths(1);
        this.Loaded += new RoutedEventHandler(OrganisationTypeSView_Loaded);
    }

    void OrganisationTypeSView_Loaded(object sender, RoutedEventArgs e)
    {

    }

}

xmal

<WPFToolkit:DatePicker Grid.Column="1" Grid.Row="4" Name="dpAccStart" VerticalAlignment="Top" 
        SelectedDate="{Binding AccountStartDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" />

<WPFToolkit:DatePicker Grid.Column="1" Grid.Row="5" Name="dpAccEnd" VerticalAlignment="Top" 
        SelectedDate="{Binding AccountEndDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"/>

ViewModel

    private DateTime? _AccountStartDate;
    private DateTime? _AccountEndDate;        
    public event PropertyChangedEventHandler PropertyChanged; 

    [Required(ErrorMessage = "Account Start Date is a required field.")]
    public DateTime? AccountStartDate
    {
        get { return _AccountStartDate; }
        set
        {

            if (_AccountStartDate != DateTime.MinValue && AccountEndDate != DateTime.MinValue)
            {

                if (value > _AccountEndDate)
                {                        
                    MessageBox.Show("Start date must be less than End date");
                    value = this.AccountStartDate;                    
                }
             }
            _AccountStartDate = value;

           if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("AccountStartDate"));
            }
        }
    }

    [Required(ErrorMessage = "Account End Date is a required field.")]
    public DateTime? AccountEndDate
    {
        get { return _AccountEndDate; }
        set
        {
            if (_AccountStartDate != DateTime.MinValue && AccountEndDate != DateTime.MinValue)
            {
                if (_AccountStartDate > value)
                {
                    MessageBox.Show("End date must be after Start date");
                    value = this.AccountEndDate;
                }
            }

            _AccountEndDate = value;

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("AccountEndDate"));
            }
      }
    }
Was it helpful?

Solution 3

I fixed the problem by removing the codes "_dataContext.AccountStartDate = DateTime.Now; _dataContext.AccountEndDate = DateTime.Now.AddMonths(1);" in code behind. Since I give an initial date for the StartDate and EndDate field, it gets the initial date automatically, so the save button will be activated.

OTHER TIPS

What you want is a validation rule based on completness of your bound class. Let your ViewModel implement the INotifyDataErrorInfo interface and implement GetErrors, HasErrors, etc.

Finally add

ValidatesOnNotifyDataErrors=True 

to the binding.

This allows you to check for consistency of the entire model, not just single properties.

I suppose besides of validation you should use Save command both with CanExecute handler, which would check the values of dpAccStart and AccountEndDate, something like this:

    private DateTime? _AccountStartDate;
    private DateTime? _AccountEndDate; 

    //Your code

    RelayCommand _saveCommand;
    public ICommand SaveCmd
    {
        get
        {
            if (_saveCommand == null)
                _saveCommand = new RelayCommand(ExecuteSaveCommand, CanExecuteCommand);
            return _saveCommand;
        }
    }

    private void ExecuteSaveCommand(object parameter)
    {
        //your saving logic
    }

    private bool CanExecuteCommand(object parameter)
    {
        if (string.IsNullOrEmpty(_AccountStartDate) ||
            string.IsNullOrEmpty(_AccountEndDate))
            return false;
        return true;
    }

Then in XAML you can assign your SaveCmd command save button:

   <Button Command="{Binding SaveCmd}">

After this the WPF will automaticly check the values of of dates making it enabled or disabled according to conditions of you CanExecute handler

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top