Custom Appointment Validation

5 posts, 0 answers
  1. Art Kedzierski
    Art Kedzierski avatar
    107 posts
    Member since:
    Nov 2009

    Posted 09 Sep 2013 Link to this post

    Where is the appropriate point in the event stream to validate a custom appointment? I found a post from two years ago that suggests attaching to the edit dialog's RadButton click event, but it also mentioned that you were planning some sort of validation mechanism. Also, I'm using MVVM and not code-behind as suggested in that thread.

    What's the status on that validation mechanism?
  2. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 11 Sep 2013 Link to this post

    Hello Art,

    You could check how the validation is implemented in our RadScheduleVIew Custom Appointment and Validation online example at the following link:
    http://demos.telerik.com/silverlight/#ScheduleView/CustomAppointmentAndValidation

    The idea is that the CustomAppointment class implements IDataErrorInfo interface.
    Please review the example and if you have any questions/issues with it, write to us again.

    Regards,
    Yana
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. DevCraft banner
  4. Art Kedzierski
    Art Kedzierski avatar
    107 posts
    Member since:
    Nov 2009

    Posted 11 Sep 2013 Link to this post

    That works, thanks!

    I am having one little issue: when Category is set to a specific value, I want one of my custom fields to then become required. However, the validation visual (red-lined box) only appears around the text-box in question if text is entered and then deleted from it. How can I check a secondary field in the Category validation?

    private string ValidateCategory()
    {
        if (string.IsNullOrEmpty(this.Category.DisplayName))
        {
            return "Please select an appointment category!";
        }
        if (this.Category.DisplayName == "Case-Related")
        {
            // Validate CaseID field ???
        }
        return null;
    }
  5. Art Kedzierski
    Art Kedzierski avatar
    107 posts
    Member since:
    Nov 2009

    Posted 11 Sep 2013 Link to this post

    Another issue, this works fine for existing appointments, but when I try to create a new appointment I get the following errors (twice). It happens when I cancel the appointment dialog as well:

    Unhandled exception at line 1, column 1 in eval code
    0x800a139e - JavaScript runtime error: Unhandled Error in Silverlight Application Object reference not set to an instance of an object.   at GlobalLabManager.Models.GLMAppointment.ValidateCategory()
       at GlobalLabManager.Models.GLMAppointment.ValidateAppointment()
       at GlobalLabManager.Models.GLMAppointment.get_Error()
       at Telerik.Windows.Controls.AppointmentDialogViewModel.IsAppointmentValid()
       at Telerik.Windows.Controls.AppointmentDialogViewModel.CanConfirm()
       at Telerik.Windows.Controls.SchedulerDialogViewModel.OnQueryConfirmCommand(Object sender, CanExecuteRoutedEventArgs e)
       at Telerik.Windows.Controls.CommandBinding.OnCanExecute(Object sender, CanExecuteRoutedEventArgs e)
       at Telerik.Windows.Controls.CommandManager.FindCommandBinding(CommandBindingCollection commandBindings, Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
       at Telerik.Windows.Controls.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
       at Telerik.Windows.Controls.CommandManager.OnCanExecute(Object sender, CanExecuteRoutedEventArgs e)
       at Telerik.Windows.Controls.CanExecuteRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
       at Telerik.Windows.RadRoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at Telerik.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RadRoutedEventArgs routedEventArgs)
       at Telerik.Windows.EventRoute.InvokeHandlersImpl(Object source, RadRoutedEventArgs args, Boolean raisedAgain)
       at Telerik.Windows.RadRoutedEventHelper.RaiseEvent(DependencyObject element, RadRoutedEventArgs args)
       at Telerik.Windows.Controls.RoutedCommand.CanExecuteImpl(Object parameter, UIElement target, Boolean& continueRouting)
       at Telerik.Windows.Controls.RoutedCommand.CanExecuteInternal(Object parameter, UIElement target, Boolean& continueRouting)
       at Telerik.Windows.Controls.RadButton.CanExecuteApply()
       at Telerik.Windows.Controls.RadButton.CanExecuteChanged(Object sender, EventArgs e)
       at Telerik.Windows.Controls.WeakEventHandlerManager.CallHandler(Object sender, EventHandler eventHandler)
       at Telerik.Windows.Controls.WeakEventHandlerManager.CallWeakReferenceHandlers(Object sender, List`1 handlers)
       at Telerik.Windows.Controls.CommandManager.<RaiseRequerySuggested>b__5()

    Here's my custom appointment:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using GlobalLabManager.Web;
    using Telerik.Windows.Controls;
    using Telerik.Windows.Controls.ScheduleView;
     
    namespace GlobalLabManager.Models
    {
        /// <summary>
        /// Implements a custom appointment which corresponds to a database Reservation record
        /// </summary>
        public partial class GLMAppointment : Telerik.Windows.Controls.ScheduleView.Appointment, IDataErrorInfo
        {
            public GLMAppointment()
            {
            }
     
            #region Fields
             
            private string _caseId;
            private ObservableCollection<Attendee> _availableAttendees;
            private ObservableCollection<Attendee> _assignedAttendees;
     
            private ObservableCollection<Device> _availableDevices;
            private ObservableCollection<Device> _assignedDevices;
             
            #endregion //Fields
             
            #region Properties
             
            public string Error
            {
                get
                {
                    return this.ValidateAppointment();
                }
            }
     
            public string this[string columnName]
            {
                get
                {
                    switch (columnName)
                    {
                        case "Category":
                            return this.ValidateCategory();
                        case "Subject":
                            return this.ValidateSubject();
                        //case "CaseID":
                        //    return this.ValidateCaseID();
                        case "AvailableAttendees":
                            return this.ValidateAssignedAttendees();
                        case "AvailableDevices":
                            return this.ValidateAssignedDevices();
                    }
                    return null;
                }
            }
     
            public string CaseID
            {
                get
                {
                    return this.Storage<GLMAppointment>()._caseId;
                }
                set
                {
                    var storage = this.Storage<GLMAppointment>();
                    if (storage._caseId != value)
                    {
                        storage._caseId = value;
                        this.OnPropertyChanged(() => this.CaseID);
                    }
                }
            }
             
            public ObservableCollection<Attendee> AvailableAttendees
            {
                get
                {
                    return this.Storage<GLMAppointment>()._availableAttendees;
                }
                set
                {
                    var storage = this.Storage<GLMAppointment>();
                    if (storage._availableAttendees != value)
                    {
                        storage._availableAttendees = value;
                        this.OnPropertyChanged(() => this.AvailableAttendees);
                    }
                }
            }
     
            public ObservableCollection<Attendee> AssignedAttendees
            {
                get
                {
                    return this.Storage<GLMAppointment>()._assignedAttendees;
                }
                set
                {
                    var storage = this.Storage<GLMAppointment>();
                    if (storage._assignedAttendees != value)
                    {
                        storage._assignedAttendees = value;
                        this.OnPropertyChanged(() => this.AssignedAttendees);
                    }
                }
            }
             
            public ObservableCollection<Device> AvailableDevices
            {
                get
                {
                    return this.Storage<GLMAppointment>()._availableDevices;
                }
                set
                {
                    var storage = this.Storage<GLMAppointment>();
                    if (storage._availableDevices != value)
                    {
                        storage._availableDevices = value;
                        this.OnPropertyChanged(() => this.AvailableDevices);
                    }
                }
            }
             
            public ObservableCollection<Device> AssignedDevices
            {
                get
                {
                    return this.Storage<GLMAppointment>()._assignedDevices;
                }
                set
                {
                    var storage = this.Storage<GLMAppointment>();
                    if (storage._assignedDevices != value)
                    {
                        storage._assignedDevices = value;
                        this.OnPropertyChanged(() => this.AssignedDevices);
                    }
                }
            }
     
            #endregion //Properties
     
            #region Methods
     
            public override IAppointment Copy()
            {
                IAppointment customAppt = new GLMAppointment();
                customAppt.CopyFrom(this);
                return customAppt;
            }
             
            public override void CopyFrom(IAppointment other)
            {
                GLMAppointment customAppt = other as GLMAppointment;
                if (customAppt != null)
                {
                    this.CaseID = customAppt.CaseID;
                    this.AvailableAttendees = customAppt.AvailableAttendees;
                    this.AssignedAttendees = customAppt.AssignedAttendees;
                    this.AvailableDevices = customAppt.AvailableDevices;
                    this.AssignedDevices = customAppt.AssignedDevices;
                }
                base.CopyFrom(other);
            }
     
            protected override void OnPropertyChanged(string propertyName)
            {
                base.OnPropertyChanged(propertyName);
     
                if (propertyName == "Category" ||
                    propertyName == "Subject" ||
                    propertyName == "AssignedAttendees" ||
                    propertyName == "AssignedDevices")
                {
                    CommandManager.InvalidateRequerySuggested();
                }
            }
             
            private string ValidateAppointment()
            {
                string errorString = this.ValidateCategory();
                errorString += this.ValidateSubject();
                errorString += this.ValidateAssignedAttendees();
                errorString += this.ValidateAssignedDevices();
     
                return errorString;
            }
     
            private string ValidateCategory()
            {
                if (string.IsNullOrEmpty(this.Category.DisplayName))
                {
                    return "Please select an appointment category!";
                }
                return null;
            }
     
            private string ValidateSubject()
            {
                if (string.IsNullOrEmpty(this.Subject))
                {
                    return "The subject cannot be empty!";
                }
                return null;
            }
     
            //private string ValidateCaseID()
            //{
            //    if (this.Category.DisplayName == "Case-Related" && string.IsNullOrEmpty(this.CaseID))
            //    {
            //        return "Case ID is required for any case-related appointment!";
            //    }
            //    return null;
            //}
     
            private string ValidateAssignedAttendees()
            {
                if (this.AssignedAttendees == null)
                {
                    return "At least one Attendee is required!";
                }
                return null;
            }
     
            private string ValidateAssignedDevices()
            {
                if (this.AssignedDevices == null)
                {
                    return "At least one device is required!";
                }
                return null;
            }
             
            #endregion //Methods
        }
    }
  6. Yana
    Admin
    Yana avatar
    4554 posts

    Posted 16 Sep 2013 Link to this post

    Hello Art,

    The custom appointment seems correct. I would ask you to send us a simple runnable project with the customized EditAppointmentDialog as well - in this way we will be able to test the exact scenario. Please open a support ticket and attach the project there.

    Thanks in advance.

    Regards,
    Yana
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
Back to Top
DevCraft banner