Стиль для окна wpf

Окна нестандартной формы

Окна необычной формы часто являются товарным знаком современных прикладных приложений вроде редакторов фотографий, программ для создания кинофильмов и МРЗ-проигрывателей; скорее всего, они будут встречаться в WPF-приложениях даже более часто.

В создании базового приложения нестандартной формы в WPF нет ничего сложного. Однако создание привлекательного профессионально выглядящего окна необычной формы требует немалых усилий — и, нередко, привлечения талантливого дизайнера графики для создания эскизов и фоновой графики.

Базовая процедура для создания окна нестандартной формы подразумевает выполнение следующих шагов:

Установите для свойства Window.AllowsTransparency значение true.

Установите для свойства Window.WindowStyle значение None, чтобы скрыть не клиентскую область окна (рамку голубого цвета). Если этого не сделать, при попытке показать окно появится ошибка InvalidOperationException.

Установите для фона (свойства Background) прозрачный цвет (цвет Transparent, значение альфа-канала которого равно нулю). Или же сделайте так, чтобы для фона использовалось изображение, имеющее прозрачные области (с нулевым значением альфа-канала).

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

Читайте также:  Вязание крючком самое красивое для дома своими руками

Предоставить фоновую графику, используя файл такого формата, который поддерживает прозрачность. Например, для фона можно использовать файл PNG. Это простой прямолинейный подход, и он очень удобен, если приходится работать с дизайнерами, которые не разбираются в XAML. Однако из-за того, что окно будет визуализироваться с большим количеством пикселей и более высокими системными параметрами DPI фоновая графика может приобрести искаженный вид. Это также может представлять проблему и в случае разрешения пользователю изменять размеры окна.

Использовать доступные в WPF функции для рисования формы, чтобы создать фон с векторным содержимым. Такой подход исключает потерю качества, какими бы ни были размеры окна и настройка DPI системы. Однако в этом случае наверняка потребуется использовать средство проектирования, поддерживающее XAML, такое как Expression Blend.

Использовать более простой WPF-элемент, имеющий необходимую форму. Например, окно с замечательными скругленными углами можно создать с помощью элемента Border. Такой подход позволяет создавать окна с современным внешним видом в стиле Office без применения каких-либо дизайнерских навыков.

Ниже в качестве примера приведен код создания пустого прозрачного окна с применением первого подхода и предоставлением файла PNG для прозрачных областей:

Это окно необычной формы (состоящее из окружности и квадрата) имеет не только пробелы, сквозь которые может просматриваться находящееся за ним содержимое, но кнопки, которые выходят за границы изображения и накладываются на прозрачную область, из-за чего кажется, будто бы они существуют сами по себе, без окна:

Те, кому приходилось программировать с использованием Windows Forms ранее, наверняка заметят, что окна нестандартной формы в WPF имеют более четкие края, особенно на изгибах. Все дело в том, что WPF умеет выполнять сглаживание между фоном окна и находящимся за ним содержимым для создания более гладкого края.

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

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

Для завершения внешнего вида этого окна осталось создать только кнопки, имитирующие размещаемые в правом верхнем углу стандартные кнопки для разворачивания, сворачивания и закрытия окна.

Источник

Шаблон окна

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

Первым делом нужно изучить предлагаемый по умолчанию шаблон элемента управления для класса Window. В основном он довольно прост, но включает в себя одну, возможно, неожиданную деталь — элемент AdornerDecorator. Этот элемент создает поверх остальной части клиентского содержимого окна специальную область рисования, называемую . Элементы управления WPF могут использовать этот слой для прорисовывания содержимого, которое должно налагаться поверх других элементов.

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

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

Элементом самого верхнего уровня в данном шаблоне является объект Border, который отвечает за рамку окна. Внутри него размещается элемент Grid с тремя строками. Содержимое элемента Grid распределяется следующим образом:

В самой верхней строке размещается строка заголовка, которая состоит из обычного элемента TextBlock, отображающего заголовок окна и кнопку закрытия. Привязка шаблона извлекает заголовок окна из свойства Window.Title.

В средней строке размещается вложенный элемент Border с остальной частью содержимого окна. Это содержимое вставляется с использованием элемента Content Presenter. Элемент ContentPresenter помещается в оболочку AdornerDecorator, что гарантирует размещение поверх него декоративного слоя.

В третьей строке размещается еще один элемент ContentPresenter. Он извлекает свое содержимое не из свойства Window.Content с помощью стандартной привязки, а получает его явно из свойства Window.Tag. Обычно это содержимое представляет собой обычный текст, но может включать любой другой элемент.

Свойство Tag используется потому, что в классе Window не предусмотрено свойства, предназначенного для указания текста нижнего колонтитула. Другим возможным вариантом является создание специального класса, унаследованного от Window, и добавление к нему дополнительного свойства Footer.

В третьей строке также размещается элемент захвата и изменения размера. Он отображается триггером, когда свойство Window.ResizeMode установлено в CanResizeWithGrip.

И, наконец, последними идут два невидимых прямоугольника, которые размещаются вдоль правого и нижнего края элемента Grid (и, соответственно, самого окна). Они позволяют пользователю изменять размеры окна щелчком и перетаскиванием.

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

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

Здесь имеется лишь одна проблема. В настоящий момент окно не обладает большей частью базового поведения, которое требуется окнам. Например, его нельзя ни перетаскивать по рабочему столу, ни изменять в размерах, ни закрывать с помощью соответствующей кнопки. Для выполнения этих действий необходим соответствующий код.

Существует два возможных способа для добавления необходимого кода: расширение примера до специального класса, производного от Window, либо создание класса отделенного кода для словаря ресурсов. Подход с созданием специального класса лучше с точки зрения инкапсуляции и позволяет расширять общедоступный интерфейс окна (например, добавлять полезные методы и свойства, пригодные для использования в приложении).

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

Источник

Стили, триггеры и темы

Стили

Стили позволяют определить набор некоторых свойств и их значений, которые потом могут применяться к элементам в xaml. Стили хранятся в ресурсах и отделяют значения свойств элементов от пользовательского интерфейса. Также стили могут задавать некоторые аспекты поведения элементов с помощью триггеров. Аналогом стилей могут служить каскадные таблицы стилей (CSS), которые применяются в коде html на веб-страницах.

Зачем нужны стили? Стили помогают создать стилевое единообразие для определенных элементов. Допустим, у нас есть следующий код xaml:

Зесь обе кнопки применяют ряд свойств с одними и теми же значениями:

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

Однако в реальности код раздувается, опть же приходится писать много повторяющейся информации. И в этом плане стили предлагают более элегантное решение:

Результат будет тот же, однако теперь мы избегаем не нужного повторения. Более того теперь мы можем управлять всеми нужными нам свойствами как единым целым — одним стилем.

Стиль создается как ресурс с помощью объекта Style , который представляет класс System.Windows.Style . И как любой другой ресурс, он обязательно должен иметь ключ. С помощью коллекции Setters определяется группа свойств, входящих в стиль. В нее входят объекты Setter , которые имеют следующие свойства:

Property : указывает на свойство, к которому будет применять данный сеттер. Имеет следующий синтаксис: Property=»Тип_элемента.Свойство_элемента» . Выше в качестве типа элемента использовался Control, как общий для всех элементво. Поэтому данный стиль мы могли бы применить и к Button, и к TextBlock, и к другим элементам. Однако мы можем и конкретизировать элемент, например, Button:

Value : устанавливает значение

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

TargetType

Hам необязательно прописывать для всех кнопок стиль. Мы можем в самом определении стиля с помощью свойства TargetType задать тип элементов. В этом случае стиль будет автоматически применяться ко всем кнопкам в окне:

Причем в этом случае нам уже не надо указывать у стиля ключ x:Key несмотря на то, что это ресурс.

Также если используем свойство TargetType, то в значении атрибута Property уже необязательно указывать тип, то есть Property=»Control.FontFamily» . И в данном случае тип можно просто опустить: Property=»FontFamily»

Если же необходимо, чтобы к какой-то кнопке не применялся автоматический стиль, то ее стилю присваивают значение null

Определение обработчиков событий с помощью стилей

Кроме коллекции Setters стиль может определить другую коллекцию — EventSetters , которая содержит объекты EventSetter . Эти объекты позволяют связать события элементов с обработчиками. Например, подключим все кнопки к одному обработчику события Click :

Соответственно в файле кода c# у нас должен быть определен обработчик Button_Click:

Наследование стилей и свойство BasedOn

У класса Style еще есть свойство BasedOn , с помощью которого можно наследовать и расширять существующие стили:

Cвойство BasedOn в качестве значения принимает существующий стиль, определяя его как статический ресурс. В итоге он объединяет весь функционал родительского стиля со своим собственным.

Источник

Стили и шаблоны элемента Window Window Styles and Templates

В этом разделе описываются стили и шаблоны для Window элемента управления. This topic describes the styles and templates for the Window control. Можно изменить значение по умолчанию, ControlTemplate чтобы обеспечить уникальность внешнего вида элемента управления. You can modify the default ControlTemplate to give the control a unique appearance. Дополнительные сведения см. в разделе Создание шаблона для элемента управления. For more information, see Create a template for a control.

Части окна Window Parts

WindowЭлемент управления не имеет именованных частей. The Window control does not have any named parts.

Состояния окна Window States

В следующей таблице перечислены визуальные состояния Window элемента управления. The following table lists the visual states for the Window control.

Имя VisualState VisualState Name Имя VisualStateGroup VisualStateGroup Name Описание Description
Допустимо Valid ValidationStates ValidationStates Элемент управления использует Validation класс, а Validation.HasError присоединенное свойство — false . The control uses the Validation class and the Validation.HasError attached property is false .
InvalidFocused InvalidFocused ValidationStates ValidationStates Validation.HasErrorПрисоединенное свойство имеет true фокус. The Validation.HasError attached property is true has the control has focus.
InvalidUnfocused InvalidUnfocused ValidationStates ValidationStates Validation.HasErrorПрисоединенное свойство true имеет элемент управления, не имеющий фокуса. The Validation.HasError attached property is true has the control does not have focus.

Пример для ControlTemplate окна Window ControlTemplate Example

В следующем примере показано, как определить ControlTemplate для Window элемента управления. The following example shows how to define a ControlTemplate for the Window control.

ControlTemplateИспользует один или несколько следующих ресурсов. The ControlTemplate uses one or more of the following resources.

Источник

Русские Блоги

[WPF] Настройка стиля окна с помощью WindowChrome

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

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

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

Настройка Window с помощью WindowChrome столкнется со многими проблемами, такими как максимизация размера. В этой статье объясняется, как справиться с этими деталями.

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

1. Введение

Я много лет занимался разработкой WPF и никогда не реализовывал собственный стиль окна. Рекомендуется использовать его в «Руководстве по программированию WPF» или в различных блогах. WindowStyle=»None» и AllowsTransparency=»True» Так что принимайте как должное, что все в порядке. Я недавно пришел к осознанию желания реализовать себя сам WindowStyle=»None» Метод не работает вообще по нескольким причинам:

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

Одних проблем с производительностью достаточно, чтобы отказаться WindowStyle=»None» К счастью, есть также реализация, использующая WindowChrome, но пока нет идеальной реализации, даже документации по MSDN (WindowChrome Class Слишком устарели, .NET 4.5 не имеет класса SystemParameters2, поэтому я должен сослаться на некоторые проекты с открытым исходным кодом (например,Modern UI for WPF ) Я сам это понял.

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

Основные функции Window показаны на рисунке выше. Обратите внимание, что в дополнение к стандартным кнопкам «Свернуть», «Развернуть / Восстановить» и «Закрыть», нажатие на значок также должно открыть системное меню формы и дважды щелкнуть, чтобы закрыть форму напрямую.

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

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

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

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

3. Осознать

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

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

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

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

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

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

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

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

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

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

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

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

AdornerDecorator предоставляет AdornerLayer для дочерних элементов в визуальном дереве. Без него невозможно отобразить некоторые декоративные эффекты (например, эффект «Фокус» элемента управления «Кнопка» на рисунке ниже), и AdornerDecorator должен быть установлен вне ContentPresenter окна.

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

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

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

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

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

Источник

Оцените статью
Поделиться с друзьями