Как сделать всплывающее окно wpf

Добавил пользователь Дмитрий К.
Обновлено: 11.09.2024

Я've получили два элемента управления TextBlock и всплывающее окно. Когда пользователь нажимает кнопку (событие mousedown) на объект TextBlock, я хочу, чтобы отобразить всплывающее окно. Я думаю, что я мог бы сделать это с EventTrigger на popup, но я могу'т использовать сеттеры в EventTrigger, я могу только начать раскадровки. Я хочу сделать это строго в XAML, потому что два управления в шаблоне и я не'т знаю, как я'й найдешь появившемся в код.

Это то, что концептуально я хочу сделать, но может't, потому что вы можете'т поставить сеттер в EventTrigger (например, вы можете с помощью DataTrigger):

Что является лучшим способом, чтобы показать всплывающее строго в XAML, когда событие происходит на другой элемент управления?

Я сделал что-то просто, но это работает.

Я использовал обычный выключатель, который я рестайлинг в элементе TextBlock, меняя свой шаблон. Тогда я просто привязан свойство ischecked на выключатель на свойства isopen всплывающего окна. Всплывающее окно имеет некоторые свойства, такие как StaysOpen, которые позволяют изменять закрытия.

Следующие работы в файла.

Следующий подход такой же, как и Хельге Кляйн's, за исключением того, что всплывающее окно закрывается автоматически, когда вы щелкните за пределами всплывающего окна (включая сам выключатель):

назальный BoolInverter; используется в IsHitTestVisible привязки, так что, когда вы снова нажмите выключатель, всплывающее окно закрывается:

Я обнаружила одну проблему с этой техникой: в WPF глючит, когда два окна на экране одновременно. В частности, если ваш выключатель о "переполнение всплывающее окно" в панели инструментов, то будут два всплывающие окна открываются после нажатия на нее. Затем вы можете обнаружить, что второй всплывающего (контекстного) будет оставаться открытым, когда вы щелкните в любом месте на вашем окне. В этот момент, закрывая всплывающее сложно. Пользователь не может повторно нажмите на выключатель, чтобы закрыть всплывающее окно, потому что IsHitTestVisible является ложным, потому что раскрывается! В мое приложение я должен использовать несколько хаков, чтобы смягчить эту проблему, например, следующий тест на главное окно, в котором написано (в голосе Луи черный) "если всплывающее окно открыто, и пользователь щелкает где-то за пределами всплывающего окна закройте, блин' всплывающее окно.&я:

Прежде, чем я получу нормальные стоны о том, чтобы сделать это "правильно".

    Я не писал приложение, просто поставил задачу повысить производительность (и/или восприятие производительности) без полного перерасхода. В какой-то момент я надеюсь, что я смогу изменить инструмент для этого приложения, пока на него не будут исправлены небольшие хитрости. Нет кода ViewModel. действительно, действительно связан с пользовательским интерфейсом. (Как я уже сказал, я не был прав в приложении) По разным причинам я не могу использовать потоки в этом сценарии, не нарушая слишком много других peices в приложении и мои временные ограничения.

Итак, есть ли способ сделать это в этом сценарии (btw. нет ViewModel, и я не могу создать его прямо сейчас из-за жесткой связи Logic-UI)?

Я просто хочу открыть WPF Popup с задержкой, вроде ToolTip.

Как я могу это достичь?

И, кстати, Popup.PopupAnimation = PopupAnimation.Fade. затухает слишком быстро. Я хочу, по крайней мере, на полсекунды.

ОТВЕТЫ

Ответ 1

Сначала. кредит для этого ответа идет на Эрик Берк. Он ответил на этот вопрос, размещенный в группе WPF Disciples. Я подумал, что было бы полезно поставить этот ответ на StackOverflow тоже.

В принципе, вам нужно оживить свойство IsOpen всплывающего окна с помощью DiscreteBooleanKeyFrame.

Обратите внимание на следующий xaml (который можно легко вставить в Kaxaml или другую свободную утилиту редактирования xaml):

Обратите внимание, что я немного изменил свое первоначальное решение. чтобы вызвать IsOpen на мыши, вместо проверки CheckBox, как и у него. Все в попытке заставить Popup вести себя немного как ToolTip.

Ответ 2

Вы можете создать стиль, который будет применен к Popup следующим образом:

Затем, всякий раз, когда вы хотите использовать его, вы будете писать разметку, подобную этой (обратите внимание на привязку для PlacementTarget):

Ответ 3

Вложенный ответ cplotts хорош, но может не применяться в вашем случае, потому что он оставляет анимацию, прикрепленную к свойству IsOpen, эффективно блокируя ее на месте и предотвращая ее изменение с помощью настройки прямого свойства, привязки и других способов. Это может затруднить использование вашего кода в зависимости от того, как вы его используете.

Если это так, я бы переключился на запуск DispatcherTimer, когда вы хотите открыть всплывающее окно после некоторой задержки, например:

Для поведения типа ToolTip это можно сделать на MouseEnter. Если вы хотите отменить всплывающее окно по какой-либо причине (например, если мышь покидает элемент управления до появления всплывающего окна), просто:

Обновление

Так как cplotts, рассмотренные в комментарии, вы также захотите установить _popup.IsOpen = false в некоторых ситуациях в событии MouseLeave, в зависимости от вашей логики для обработки событий ввода/вывода мыши между вашим элементом управления и всплывающим окном. Имейте в виду, что вы обычно не хотите слепо устанавливать IsOpen=false в каждое событие MouseLeave, потому что это может произойти, когда всплывающее окно появляется над ним. В некоторых ситуациях это приведет к появлению мерцающего всплывающего окна. Поэтому вам понадобится какая-то логика.

Ответ 4

Ответ 5

Вы можете расширить XAML для этого решения, чтобы всплывающее окно оставалось открытым, пока мышь над ним, затем автоматически исчезает.

Я модифицировал образец следующим образом:

  • Создайте анимацию "ClosePopop", которая устанавливает IsOpen в False через 0,5 секунды. Я сделал это ресурсом, потому что он использовался дважды.
  • Для управляющего триггера IsMouseOver добавьте ExitAction, который запустит анимацию ClosePopup. Это дает пользователю возможность переместить указатель мыши над всплывающим окном, прежде чем он закроется. Я назвал эту анимацию "bxb"
  • Добавить триггер для всплывающего свойства IsMouseOver. На mouseover остановите (но не удаляйте) оригинальную анимацию Closexopup "bxb". Это оставляет всплывающее окно видимым; удаление анимации здесь приведет к закрытию всплывающего окна.
  • В выпадающем меню мыши запустите новую анимацию ClosePopup и удалите анимацию "bxb". Последний шаг критический, потому что в противном случае первая, остановленная анимация "bxb" сохранит всплывающее окно.

Эта версия превращает синюю попку, пока мышь над ней, чтобы вы могли видеть последовательность событий с помощью Kaxaml.



В данный Frame я выгружаю различные представления.



В данный Frame я выгружаю различные представления.

Можно же просто бэкграунд окна сделать прозрачным и черным, вот и будет затемнение
что-то вроде такого:

Можно же просто бэкграунд окна сделать прозрачным и черным, вот и будет затемнение
что-то вроде такого:

Control (Theme resource):

Вот прозрачный затемненный фон, который блокирует все что сзади и непрозрачные контролы на нем, по которым можно щелкать.
Или я неправильно понял?

Поскольку содержание устарело, вместо этой статьи была написана новая статья, пожалуйста, обратитесь к новой статье:

В этой статье рассматриваются элементы пользовательского интерфейса и поведение стандартного окна. Окно (форма) является одним из наиболее часто используемых элементов пользовательского интерфейса, будь то настольное программирование или повседневное использование. Поскольку Window так важен и важен, его понимание не причиняет вреда.

Представьте принцип и различные детали использования WindowChrome для настройки Window.

Поскольку в родном окне WPF в RibbonWindow есть много ошибок в пользовательском интерфейсе, я предоставил настраиваемое окно RibbonWindow для решения этих проблем.

1. Введение

  • Было бы ужасно, если бы в Window не было теней, но добавление DropShadowEffect в одиночку сильно повлияло бы на производительность.
  • Потребность настроить всплывающее окно, закрыть, развернуть, свернуть анимацию и сделать это самостоятельно, безусловно, не так эффективна, как собственная анимация Windows.
  • Необходимо реализовать функцию изменения размера.
  • Другие ошибки

2. Основные оконные функции

38937-20170908134528241-459542101.jpg

38937-20170907154643179-964997365.jpg

Я хочу добиться эффекта окна, похожего на Office 2016: тени, пользовательские цвета форм. Для теней и анимационных эффектов вы можете оставить системные настройки по умолчанию, которые в основном будут выглядеть хорошо.

38937-20170907154654116-809601816.jpg

Большинство пользовательских окон имеют закругленные углы, но мне это не нравится. Закругленные углы с несколькими пикселями обычно не очень закруглены при низком DPI (см. Рисунок ниже), поэтому сохраняйте правильные углы.

38937-20170907154701679-1472738296.jpg

Кроме того, цвет строки заголовка изменяется в активном и неактивном состояниях:

38937-20170908103142944-1682110124.jpg

Конечный результат выглядит следующим образом:

3. Осознать

3.1 Определите элемент управления CustomWindow

Во-первых, чтобы облегчить будущее расширение, я определил шаблонный элемент управления с именем CustomWindow, полученный из Window.

В основном добавлено несколько CommandBindings для кнопок привязки в строке заголовка.

3.2 Использование WindowChrome

Для WindowChrome,MSDNЭто описано так:

Чтобы настроить окно, сохранив его стандартные функции, вы можете использовать класс WindowChrome. Функциональность WindowChrome-подобной оконной рамки разделяет визуальные объекты и позволяет контролировать границу между клиентом и нерабочей областью окна приложения.

Добавьте следующие параметры в DefaultStyle CustomWindow:

В дополнение к границе, содержащей тень, содержимое всего окна может быть задано пользователем.

3.3 Базовое расположение окон

Стандартный макет окна прост, примерно строка заголовка и содержание.
PART_WindowTitleGrid - строка заголовка, конкретный контент будет обсуждаться в следующем разделе.

Содержимое ContentPresenter является клиентской областью окна.

38937-20170907154739601-1800999977.jpg

ResizeGrip это когда ResizeMode = ResizeMode.CanResizeWithGrip; Дескриптор изменения размера в нижнем правом углу окна, который появляется, когда окно в основном используется для запроса окна, можно изменить, перетаскивая границу.

3.4 Строка заголовка макета

Кнопки в строке заголовка реализованы, как указано выше, привязывают Command к SystemCommands и устанавливают WindowChrome.IsHitTestVisibleInChrome="True" Содержимое в строке заголовка должно устанавливать это дополнительное свойство, чтобы реагировать на операции мыши.

Значок в строке заголовка также является кнопкой. Автономно открывает SystemMenu и дважды щелкает, чтобы закрыть окно. Значения высоты и ширины используются отдельно SystemParameters.SmallIconHeight и SystemParameters.SmallIconWidth SystemParameters содержит атрибуты, которые можно использовать для запроса настроек системы. Всегда правильно использовать SystemParameters везде, где это возможно.

Стиль кнопки реализован не очень хорошо, это будет немного пока, и это будет улучшено в будущем.

3.5 Обработка триггеров

Хотя мне обычно нравится использовать VisualState для реализации перехода между пользовательским интерфейсом шаблонного элемента управления и состоянием, иногда триггер удобен и быстр, особенно когда анимация не нужна.
Обратите внимание, что когда WindowState = Maximized, Margin of LayoutRoot должен быть установлен на 7. Если вы этого не сделаете, край окна будет замаскирован при максимизации. Многие решения, использующие WindowChrome для настройки окна, недоступны. Смирись с этим.

3.6 Управление навигацией

Еще один момент, на который стоит обратить внимание, это клавиатурная навигация. В общем, если вы нажимаете клавишу Tab в окне, фокус будет циклически перемещаться по содержимому окна. Не позволяйте кнопкам в строке заголовка получить фокус и не позволяйте родительским элементам ContentPresenter получить фокус, поэтому установите его на ContentPresenter KeyboardNavigation.TabNavigation="Cycle" , Чтобы кнопки в строке заголовка не фокусировались, они также установлены на каждой кнопке IsTabStop="False" ,

3.7 DragMove

Некоторым людям нравится больше, чем просто строка заголовка. Вы можете перетащить Окно, удерживая любую пустую часть окна, просто добавьте DragMove в свой код:

3.8 Портирование Переходя ContentControl

Просто позвольте содержанию окна также добавить анимацию. Я буду Silverlight Инструментарий TransitioningContentControl Скопируйте его, только немного измените анимацию и OnApplyTemplate() Наконец добавил это предложение: VisualStateManager.GoToState(this, Transition, true); , Наконец, замените ContentPresenter в Window этим элементом управления, эффект не плохой (реальный эффект довольно плавный, но GIF выглядит не очень хорошо):

3.9 Проблема SizeToContent

38937-20170907154755522-511004026.jpg

Существует более неприятная проблема при настройке SizeToContent="WidthAndHeight" Когда вы откроете Window, вы получите следующую ошибку.

Кажется, что размер содержимого и размер окна рассчитаны неправильно.В настоящее время решение заключается в добавлении следующего кода в CustomWindow, который прост и груб, но может вызвать другие проблемы:

5. Заключение

В первый раз, когда я написал стиль Window, я не мог придумать так много мест, на которые стоит обратить внимание
В настоящее время это очень простая демонстрация, без добавления дополнительных функций, надеюсь, она будет полезна другим.
Кодировка выполняется в Window10 и только немного протестирована в Windows7, я не смею гарантировать совместимость.
Пожалуйста, укажите на любые ошибки или упущения.

Читайте также: