/// <summary>
        /// Handle contains logic to save changes, start new operation or process errors when solve conpleted.
        /// </summary>
        /// <param name="sender">Solver.</param>
        /// <param name="e">Solve completed event args.</param>
        private void Solver_AsyncSolveCompleted(object sender, AsyncSolveCompletedEventArgs e)
        {
            // If event came from any else solve operation - exit.
            if (e.OperationId != _currentOperationId)
            {
                return;
            }

            AsyncOperationInfo info = null;

            App.Current.Solver.GetAsyncOperationInfo(e.OperationId, out info); // Get operation info.

            // If operation complete successful.
            if (e.Error == null && !e.Cancelled && !e.Result.IsFailed)
            {
                Schedule changedSchedule = info.Schedule;
                _ProcessSaveSchedule(changedSchedule, info);                                           // Save edited schedule.
                _SetScheduleProcessed(changedSchedule);                                                // Set schedule Processed to "true".
                App.Current.Messenger.AddInfo(_FormatSuccessSolveCompletedMsg(changedSchedule, info)); // Add info message.
                _NotifyScheduleChanged(changedSchedule);

                UnassignScheduleInfo nextInfo = null;

                if (_GetNextScheduleToUnassign(out nextInfo))
                {
                    _StartNextScheduleUnassigning(nextInfo);
                    return;
                }

                _ProcessOrders(_args); // Call abstract method _ProcessOrders overrided in child command (to move orders to other date or delete them).
            }
            else if (e.Error != null)  // If Error occured during operation.
            {
                Logger.Error(e.Error);
                CommonHelpers.AddRoutingErrorMessage(e.Error);

                if (e.Result != null) // Result is "null" when connection failed.
                {
                    // Create violations collection.
                    ICollection <MessageDetail> details = _GetErrorFailedDetails(info, e.Result);
                    _ShowFailedMessage(e.Error, info.Schedule, details); // Show failed message.
                }
            }
            else if (e.Cancelled) // If operation was cancelled.
            {
                App.Current.Messenger.AddInfo(_FormatCancelMsg(info.Schedule));
            }
            else if (e.Result.IsFailed) // If operation's failed.
            {
                // Create violations collection.
                ICollection <MessageDetail> details = _GetErrorFailedDetails(info, e.Result);
                _ShowFailedMessage(e.Error, info.Schedule, details);
            }

            _UpdateOptimizeAndEditPageSchedules();  // Update optimize and edit page content.
            _CleanUp();
            _UnlockUI();
        }
        /// <summary>
        /// Method sets schedule Processed status to true
        /// </summary>
        private void _SetScheduleProcessed(Schedule schedule)
        {
            int scheduleInfoIndex = _GetInfoIndexBySchedule(schedule);

            if (scheduleInfoIndex != -1)
            {
                UnassignScheduleInfo processedInfo = _schedulesToUnassign[scheduleInfoIndex];
                processedInfo.IsProcessed = true;
                _schedulesToUnassign[scheduleInfoIndex] = processedInfo;
            }
        }
        /// <summary>
        /// Returns true if next UnassignScheduleInfo is found and sets its into out object.
        /// Otherwise returns false and sets out object to null.
        /// </summary>
        /// <param name="info">Schedule info.</param>
        /// <returns>True - if next schedule found, otherwise - false.</returns>
        private bool _GetNextScheduleToUnassign(out UnassignScheduleInfo info)
        {
            foreach (UnassignScheduleInfo scheduleInfo in _schedulesToUnassign)
            {
                if (!scheduleInfo.IsProcessed)
                {
                    info = scheduleInfo;
                    return(true);
                }
            }

            info = null;
            return(false);
        }
 /// <summary>
 /// Method start unassign orders from next schedule from list.
 /// </summary>
 /// <param name="schedule"></param>
 /// <returns></returns>
 private void _StartNextScheduleUnassigning(UnassignScheduleInfo info)
 {
     _UnassignOrdersFromSchedule(info.Schedule, info.OrdersToUnassign);
 }
 /// <summary>
 /// Method start unassign orders from next schedule from list.
 /// </summary>
 /// <param name="schedule"></param>
 /// <returns></returns>
 private void _StartNextScheduleUnassigning(UnassignScheduleInfo info)
 {
     _UnassignOrdersFromSchedule(info.Schedule, info.OrdersToUnassign);
 }
        /// <summary>
        /// Returns true if next UnassignScheduleInfo is found and sets its into out object.
        /// Otherwise returns false and sets out object to null.
        /// </summary>
        /// <param name="info">Schedule info.</param>
        /// <returns>True - if next schedule found, otherwise - false.</returns>
        private bool _GetNextScheduleToUnassign(out UnassignScheduleInfo info)
        {
            foreach (UnassignScheduleInfo scheduleInfo in _schedulesToUnassign)
            {
                if (!scheduleInfo.IsProcessed)
                {
                    info = scheduleInfo;
                    return true;
                }
            }

            info = null;
            return false;
        }