/// <summary>
        /// Make postponed call bring item into view, if item was add to selection by click in mapview or timeview.
        /// </summary>
        /// <param name="args">Collection changed args.</param>
        private void _CallBringItemIntoViewIfNeeded(NotifyMultiCollectionChangedEventArgs args)
        {
            Debug.Assert(_optimizeAndEditPage != null);
            Debug.Assert(_mapView != null);
            Debug.Assert(_timeView != null);
            Debug.Assert(args != null);

            if (!_postponedBringItemIntoViewInvoked && args.EventArgs.Action == NotifyCollectionChangedAction.Add &&
                (args.Initiator == _mapView.SelectedItems || args.Initiator == _timeView.SelectedItems))
            {
                _optimizeAndEditPage.Dispatcher.BeginInvoke(new BringToViewDelegate(_BringItemIntoView),
                                                            DispatcherPriority.Input, args.EventArgs.NewItems[0]);

                _postponedBringItemIntoViewInvoked = true;
            }
        }
        /// <summary>
        /// React on changes in multicollection binding.
        /// </summary>
        /// <param name="sender">Ignored.</param>
        /// <param name="e">Multi collection changed event args.</param>
        private void _CollectionBindingNotifyMultiCollectionChanged(object sender, NotifyMultiCollectionChangedEventArgs e)
        {
            IList initiator = e.Initiator;

            DataGridControlEx initiatorGrid = null;

            if (initiator == _routesView.RoutesGrid.SelectedItems)
            {
                initiatorGrid = _routesView.RoutesGrid;
            }
            else if (initiator == _ordersView.OrdersGrid.SelectedItems)
            {
                initiatorGrid = _ordersView.OrdersGrid;
            }

            // Check that need to clear selection - if initiator is selected items of datagridcontrol and item was add.
            if ((e.EventArgs.Action == NotifyCollectionChangedAction.Add || e.EventArgs.Action == NotifyCollectionChangedAction.Replace) &&
                initiatorGrid != null && initiatorGrid.SelectedItemsFromAllContexts.Count > 0)
            {
                object firstSelectedItem = e.EventArgs.NewItems[0];

                // In case of shift or control adding element need to check type of new element.
                // if type of new element can't be selected with old selected.
                bool needToClearCollections = true;
                if (Keyboard.Modifiers == ModifierKeys.Control || Keyboard.Modifiers == ModifierKeys.Shift)
                {
                    needToClearCollections = !_CanSelect(firstSelectedItem);
                }

                if (needToClearCollections && !_postponedSelectionClearInvoked)
                {
                    _optimizeAndEditPage.Dispatcher.BeginInvoke(new DelegateWithItemParam(_PostponedClearingInvoked),
                                                                DispatcherPriority.Send, firstSelectedItem);

                    _postponedSelectionClearInvoked = true;
                }
            }

            _CallBringItemIntoViewIfNeeded(e);

            if (NotifyMultiCollectionChanged != null)
            {
                NotifyMultiCollectionChanged(sender, e);
            }
        }
        /// <summary>
        /// React on changes in multi collection binding.
        /// </summary>
        /// <param name="sender">Ignored.</param>
        /// <param name="e">Collection changed event args.</param>
        private void _SelectionManagerNotifyMultiCollectionChanged(object sender, NotifyMultiCollectionChangedEventArgs e)
        {
            if (e.Initiator == RoutesGrid.SelectedItems)
                return;

            // If collection reset - reset also selected items in all child contexts.
            if (e.EventArgs.Action == NotifyCollectionChangedAction.Reset)
            {
                IEnumerable<DataGridContext> childContexts = RoutesGrid.GetChildContexts();
                foreach (DataGridContext dataGridContext in childContexts)
                    dataGridContext.SelectedItems.Clear();
            }
            else if (e.EventArgs.NewItems != null && e.EventArgs.NewItems.Count > 0)
            {
                // If stop added - bring it to view.
                Stop stopToBringIntoView = null;
                foreach (object obj in e.EventArgs.NewItems)
                {
                    Stop stop = obj as Stop;
                    if (stop != null)
                    {
                        _AddStopToSelection(stop);

                        if (stopToBringIntoView == null)
                            stopToBringIntoView = stop; // store first
                    }
                }

                if (stopToBringIntoView != null)
                {
                    RoutesGrid.BringItemIntoView(stopToBringIntoView);
                }
            }
        }
        /// <summary>
        /// React on changes in multicollection binding.
        /// </summary>
        /// <param name="sender">Ignored.</param>
        /// <param name="e">Multi collection changed event args.</param>
        private void _CollectionBindingNotifyMultiCollectionChanged(object sender, NotifyMultiCollectionChangedEventArgs e)
        {
            IList initiator = e.Initiator;

            DataGridControlEx initiatorGrid = null;
            if (initiator == _routesView.RoutesGrid.SelectedItems)
            {
                initiatorGrid = _routesView.RoutesGrid;
            }
            else if (initiator == _ordersView.OrdersGrid.SelectedItems)
            {
                initiatorGrid = _ordersView.OrdersGrid;
            }

            // Check that need to clear selection - if initiator is selected items of datagridcontrol and item was add.
            if ((e.EventArgs.Action == NotifyCollectionChangedAction.Add || e.EventArgs.Action == NotifyCollectionChangedAction.Replace) &&
                initiatorGrid != null && initiatorGrid.SelectedItemsFromAllContexts.Count > 0)
            {
                object firstSelectedItem = e.EventArgs.NewItems[0];

                // In case of shift or control adding element need to check type of new element.
                // if type of new element can't be selected with old selected.
                bool needToClearCollections = true;
                if (Keyboard.Modifiers == ModifierKeys.Control || Keyboard.Modifiers == ModifierKeys.Shift)
                    needToClearCollections = !_CanSelect(firstSelectedItem);

                if (needToClearCollections && !_postponedSelectionClearInvoked)
                {
                    _optimizeAndEditPage.Dispatcher.BeginInvoke(new DelegateWithItemParam(_PostponedClearingInvoked),
                        DispatcherPriority.Send, firstSelectedItem);

                    _postponedSelectionClearInvoked = true;
                }
            }

            _CallBringItemIntoViewIfNeeded(e);

            if (NotifyMultiCollectionChanged != null)
                NotifyMultiCollectionChanged(sender, e);
        }
        /// <summary>
        /// Make postponed call bring item into view, if item was add to selection by click in mapview or timeview.
        /// </summary>
        /// <param name="args">Collection changed args.</param>
        private void _CallBringItemIntoViewIfNeeded(NotifyMultiCollectionChangedEventArgs args)
        {
            Debug.Assert(_optimizeAndEditPage != null);
            Debug.Assert(_mapView != null);
            Debug.Assert(_timeView != null);
            Debug.Assert(args != null);

            if (!_postponedBringItemIntoViewInvoked && args.EventArgs.Action == NotifyCollectionChangedAction.Add &&
                (args.Initiator == _mapView.SelectedItems || args.Initiator == _timeView.SelectedItems))
            {
                _optimizeAndEditPage.Dispatcher.BeginInvoke(new BringToViewDelegate(_BringItemIntoView),
                        DispatcherPriority.Input, args.EventArgs.NewItems[0]);

                _postponedBringItemIntoViewInvoked = true;
            }
        }