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; } } }