private void openMenu( )
        {
            if (expanded)
            {
                return;
            }

            if (this.Type == MenuItemType.Submenu || Type == MenuItemType.RootSubmenu)
            {
                if (null == popup)
                {
                    popup = new Popup(this.Items, this.popupShadow, this.ActualWidth);
                    foreach (MenuItemBase itemBase in this.Items)
                    {
                        if (itemBase is MenuItem)
                        {
                            (( MenuItem )itemBase).ParentItem = this;
                        }
                    }
                    popup.AddHandler(Window.ClosedEvent, new EventHandler(onPopupClosed));
                }
                WindowsHost windowsHost = VisualTreeHelper.FindClosestParent <WindowsHost>(this);
                Point       point       = TranslatePoint(this, new Point(0, 0), windowsHost);
                popup.X = point.X;
                popup.Y = point.Y;
                windowsHost.ShowModal(popup, true);
                expanded = true;
            }
        }
        private void openPopup( )
        {
            if (opened)
            {
                throw new InvalidOperationException("Assertion failed.");
            }
            Window popup = new PopupWindow(Items, SelectedItemIndex ?? 0, shadow,
                                           ShownItemsCount != null ? ShownItemsCount.Value - 1 : ( int? )null);
            Point popupCoord = TranslatePoint(this, new Point(0, 0),
                                              VisualTreeHelper.FindClosestParent <WindowsHost>(this));

            popup.X     = popupCoord.X;
            popup.Y     = popupCoord.Y;
            popup.Width = shadow ? ActualWidth + 1 : ActualWidth;
            if (Items.Count != 0)
            {
                popup.Height = (ShownItemsCount != null ? ShownItemsCount.Value : Items.Count)
                               + (shadow ? 2 : 1); // 1 row for transparent "header"
            }
            else
            {
                popup.Height = shadow ? 3 : 2;
            }
            WindowsHost windowsHost = VisualTreeHelper.FindClosestParent <WindowsHost>(this);

            windowsHost.ShowModal(popup, true);
            opened = true;
            EventManager.AddHandler(popup, Window.ClosedEvent, new EventHandler(OnPopupClosed));
        }
        /// <summary>
        /// Обработчик отвечает за вывод на передний план неактивных окон, на которые нажали мышкой,
        /// и за обработку мыши, когда имеется модальное окно - в этом случае обработчик не пропускает
        /// события, которые идут мимо модального окна, дальше по дереву (Tunneling) - устанавливая
        /// Handled в True, либо закрывает модальное окно, если оно было показано с флагом
        /// OutsideClickClosesWindow.
        /// eventType = 0 - PreviewMouseDown
        /// eventType = 1 - PreviewMouseUp
        /// eventType = 2 - PreviewMouseMove
        /// </summary>
        private void onPreviewMouseEvents(MouseEventArgs args, int eventType)
        {
            bool handle = false;

check:
            if (isTopWindowModal( ))
            {
                Window modalWindow   = ( Window )Children[Children.Count - 1];
                Window windowClicked = VisualTreeHelper.FindClosestParent <Window>((Control)args.Source);
                if (windowClicked != modalWindow)
                {
                    if (windowInfos[modalWindow].OutsideClickClosesWindow &&
                        (eventType == 0 || eventType == 2 && args.LeftButton == MouseButtonState.Pressed))
                    {
                        // закрываем текущее модальное окно
                        CloseWindow(modalWindow);

                        // далее обрабатываем событие как обычно
                        handle = true;

                        // Если дальше снова модальное окно, проверку нужно повторить, и закрыть
                        // его тоже, и так далее. Можно отрефакторить как вызов подпрограммы
                        // вида while (closeTopModalWindowIfNeed()) ;
                        goto check;
                    }
                    else
                    {
                        // прекращаем распространение события (правда, контролы, подписавшиеся с флагом
                        // handledEventsToo, получат его в любом случае) и генерацию соответствующего
                        // парного не-preview события
                        args.Handled = true;
                    }
                }
            }
            else
            {
                handle = true;
            }
            if (handle && (eventType == 0 || eventType == 2 && args.LeftButton == MouseButtonState.Pressed))
            {
                Window windowClicked = VisualTreeHelper.FindClosestParent <Window>(( Control )args.Source);
                if (null != windowClicked)
                {
                    activateWindow(windowClicked);
                }
                else
                {
                    Menu menu = VisualTreeHelper.FindClosestParent <Menu>(( Control )args.Source);
                    if (null != menu)
                    {
                        activateMenu(  );
                    }
                }
            }
        }
        /// <summary>
        /// Interrupts wheel event propagation if its source window is not on top now.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void onPreviewMouseWheel(object sender, MouseWheelEventArgs args)
        {
            int windowsStartIndex = 0;

            if (mainMenu != null)
            {
                assert(Children[0] == mainMenu);
                windowsStartIndex++;
            }
            if (windowsStartIndex < Children.Count)
            {
                Window topWindow    = ( Window )Children[Children.Count - 1];
                Window sourceWindow = VisualTreeHelper.FindClosestParent <Window>(( Control )args.Source);
                if (topWindow != sourceWindow)
                {
                    args.Handled = true;
                }
            }
        }