иконки для wpf приложений
WPF: 4 варианта кнопки с иконкой и текстом
Я думаю что каждый (или почти каждый), из тех, кто приходит в WPF из WinForms, поначалу испытывает растерянность по поводу функционала стандартных контролов.
Казалось бы – вот он — знакомый контрол.
Он очень похож на старого знакомого из WinForms. Даже сигнатура обычных методов либо полностью совпадает, либо претерпела незначительную трансформацию (ну, например, свойство Enabled получило приставку Is). Настроек у контролов много, от параметров визуализации рябит в глазах.
Но при чуть более тесном знакомстве и попытке натянуть привычные способы построения интерфейса на XAML и приходит та самая растерянность.
Как же так? Ну неужели у кнопки нет свойства Image? Вы ведь шутите, правда?
Все дело в том, что у WPF (точнее у XAML) совершенно иная идеология организации интерфейса. Базовые контролы представляют лишь базовый (простите за тавтологию) функционал. Простота базовых контролов компенсируется мощными механизмами шаблонов и стилей.
Существуют и сторонние библиотеки компонентов, но они, чаще всего, либо бесполезны, либо безнадежно устарели, либо сильно платные.
Не так давно я в очередной раз столкнулся с необходимостью решения этой очень простой (казалось бы) задачи. Я истерзал весь гугл запросами типа “XAML button with image” “WPF button image text” и т.д.
Среди десятков просмотренных результатов нашлись очевидные как очевидные (и при этом неудобные) пути решения, так и более изощренные.
Небольшое отступление номер 1
После первых же экспериментов стало очевидно, что XAML и иконки в виде png – вещи несовместимые. Не буду долго растекаться почему так – литературы на эту тему хватает, скажу только что в итоге получается и некрасиво, и неудобно, и нефункционально. Картинки размытые, наложенные эффекты и анимация выглядят удручающе и т.д…
Но не стоит огорчаться – в сети десятки и сотни ресурсов с векторными картинками.
Лучшее из того, что я нашел – SyncFusion Metro Studio 2 (не реклама). Это бесплатный продукт, в котором есть 1700 векторных иконок и средства вывода этих иконок в XAML. Результат получается в виде сложного элемента, из которого достаточно скопировать лишь Path, который описывает саму геометрию иконки.
С этим элементом я поступаю так – в проект добавляю ResourceDictionary с именем Icons.xaml и кладу в него все нужные мне иконки:
Но давайте вернемся к способам реализации кнопки с иконкой.
Первый и самый очевидный способ – описать нужный Content кнопки прямо в коде формы
Ну, казалось бы, всё на месте. Есть кнопка, у нее есть иконка и текст. Тех, кто поверит в то, что всё так просто и попытается организовать таким подходом красивый и стильный интерфейс, очень скоро ждёт разочарование. И вот почему: простая настройка стиля приводит к распуханию XAML за счет дублирования описания параметров элементов прямо в коде формы. 10 кнопок – 10 идентичных описаний. Простое изменение типа «а давайте-ка покрасим текст на кнопках в зеленый цвет» превращается в утомительный копипаст и еще большее распухание формы.
Второй очевидный способ — наследование от Button
А давайте напишем «свою кнопку с блекджеком и сами знаете с чем еще»?
Наследуемся от Button и добавляем DependencyProperty для ContentControl, через который из XAML формы можно будет задать содержимое для иконки. Не буду останавливаться на подробностях реализации (внизу будет ссылка на источники, там можно будет почитать), но опишу минусы – содержимое кнопки придется задавать из конструктора наследника, на C#. Отсюда получаем массу очевидных и неочевидных проблем, не говоря уже о том, что это не очень хорошо пахнет.
Третий очевидный способ — создадим UserControl.
Создадим UserControl, на который покладем одну лишь кнопку. В UserControl создадим DependencyProperty, через которое будем задавать иконку для ContentControl, который лежит в кнопке. Этот способ по праву заслуживает медаль за максимальную корявость. Он наследует почти все недостатки предыдущих способов, и добавляет множество собственных. В коде формы мы получаем UserControl, но теряем кнопку. Теряем вместе со всеми свойствами и событиями. Автор идеи предлагает вытащить все, что было потеряно, через те самые DependencyProperty, в общем вы поняли. Становится непонятно за что же мы боролись.
Четвёртый способ — AttachedProperty
Этот способ я отношу к неочевидным и изощренным. В оригинале статьи автор предлагает задавать картинку через AttachedProperty. Забегая вперед скажу, что именно этот способ я и выбрал для использования в своем продукте и именно его я опишу максимально подробно. Он не лишен некоторых недостатков на этапе разработки (опишу ниже), но всё же мне он понравился больше остальных. В оригинале автор использовал иконку в виде картинки png, я же модифицировал способ для использования векторной иконки и добавил плюшек.
Итак, совсем немного теории. Что же такое это самое AttachedProperty
Каждый XAML разработчик сталкивался с Attached свойствами когда, например, задавал контролу свойство Grid.Column.
Если в трёх словах – то это своей идее немного похоже на Extension из Linq. Можно зарегистрировать свойство, значение которого можно задать любому DependencyObject. Выглядит это примерно так (пример из MSDN):
В этом коде регистрируется свойство IsBubleSource. В результате любому DependencyObject, например тому же Button, можно задать его значение:
Общий смысл этого кода – при задании свойства IsBubbleSource для кнопки мы автоматически попадаем в метод SetIsBubbleSource, который устанавливает значение. При получении значения, соответственно, попадаем в метод GetIsBubbleSource. Это все происходит автоматически, достаточно лишь написать методы с именами Set и Get, остальное – дело платформы.
Несмотря на то, что написано не так уж и мало кода, самому Button от такой операции ни жарко ни холодно – он просто становится хранилищем обособленного значения, которое можно задавать и спрашивать. Конечно, можно реализовать в методах SetIsBubbleSource и GetIsBubbleSource хитрую логику, которая будет приводить element к Button, доставать из него содержимое, и производить с содержимым различные операции, но это опять плохо пахнет, делать так не нужно.
Приступаем к практической части
Небольшое отступление 2
В оригинале автор использует имя класса EyeCandy и namespace проекта, но это слишком длинно и я надеюсь, что мне простят сокращение – namespace Ext и имя класса E.
В проект WPF добавляем следующий класс:
Что же здесь происходит? Мы зарегистрировали Attached свойство Icon типа FrameworkElement со значением по умолчанию равным null.
Теперь создадим шаблон для нашей кнопки. Я не буду останавливаться на объяснения «что такое шаблоны и как они работают» – если вдруг кому-то это неизвестно – информации в сети очень много.
Итак, добавляем в наш проект ResourceDictionary с именем Styles.xaml (если вдруг в проекте еще нет ресурса стилей). В этом ResourceDictionary добавим следующий код:
Эта запись ResourceDictionary описывает шаблон любой кнопки нашего проекта. В этом шаблоне задается обычное оформление для кнопки WPF, но переопределяется ее содержимое. В качестве содержимого выступает StackPanel, в котором лежат ContentControl и TextBlock, т.е. точно так же, как и в самом первом примере. Кроме этого в шаблоне я задал следующее поведение для иконки – если для кнопки задано IsEnabled == False, то иконка получает прозрачность 50%, и становится похожей на неактивную.
Добавим на нашу форму 4 простые кнопки. Назначим каждой кнопке свой текст, например вот так: Content=«Кнопка 1».
Запускаем приложение.
Итак, идем в наш ресурсный файл Styles.xaml и добавляем в него новый namespace:
После этого опускаемся ниже и в шаблоне кнопки находим строчку, в которой создается ContentControl и задается его содержимое:
Заменяем вторую строчку:
Эта строчка заставляет ContentControl обратиться к свойству Ext.E.Icon у кнопки и получить из него своё содержимое. После этого остается добавить код, устанавливающий значение свойства Ext.E.Icon в саму кнопку. Делается это в коде формы, на которой создается кнопка.
Примитивный вариант кнопки с иконкой готов. Меняя значение IconTriangle на имена других ресурсов, можно задавать различные иконки на кнопках. При этом, в отличии от первых трех способов, мы сохраняем у кнопки все ее врожденные способности к стилизации (за исключением возможности менять структуру Content, само собой). Содержимое кнопки задается не из C#, и все свойства с событиями остались на своем месте.
Пойдем немного дальше
Опишу лишь изменения, которые нужно сделать в шаблоне Button.
Размеры ContentControl связываем со значением IconSize:
Ориентацию StackPanel связываем со значением Orientation
В результате кнопка получила дополнительные параметры, и мы можем написать вот так:
В результате нехитрых манипуляций можно получить вот такой зоопарк (первая кнопкаIsEnabled=«False»): »
Ну и напоследок упомяну об ограничениях
Но касается это только Designer, в режиме выполнения приложения всё работает как нужно.
Возможно (и даже скорее всего) я описал велосипед, но тот факт что за два дня поисков я не нашел более приемлемой бесплатной реализации говорит о том, что на этом фронте не всё ладно.
Кроме того я получил возможность немного разобраться с механизмом расширения стандартных контролов нестандартным способом и применений этому механизму можно найти массу.
Благодарю за внимание.
UPD: Статья обновлена в связи с тем, что было найдено решение проблемы с использованием одинаковой иконки на разных кнопках.
UPD2: Благодарю onikiychuka за дельное предложение.
Значки для приложений для Windows
Значки — это визуальный ярлык для действий, концепций или продуктов. Передача значения в символическом изображении (значке) позволяет преодолеть языковые барьеры и сэкономить крайне ценный ресурс: пространство на экране.
Значки могут отображаться в приложениях и за их пределами.
Значки в приложении
Значки за пределами приложения
В этой статье описываются значки в вашем приложении. Дополнительные сведения о значках вне приложений (значки приложения) см. в статье, посвященной значкам плитки и приложения.
Когда использовать значки
Значки позволяют сэкономить место, но когда их следует использовать?
Используйте значок для действий, таких как вырезание, копирование, вставка и сохранение, или для элементов навигации в меню переходов.
Используйте значок, если он уже существует, для концепции, которую вам необходимо представить. (Чтобы узнать, существует ли значок, просмотрите список значков Segoe.)
Используйте значок, если пользователю легко понять, что он означает, и это очевидно, даже если значок небольшого размера.
Не используйте значок, если его значение непонятно или его пояснение требует сложной формы.
Использование правильного типа значка
Существует множество способов создания значка. Вы можете использовать символьный шрифт, например Segoe MDL2 Assets. Вы можете создать собственное векторное изображение. Вы можете даже использовать растровое изображение, хотя это не рекомендуется. Далее представлен обзор различных способов добавления значка в приложение.
Использование стандартного значка.
Корпорация Майкрософт предоставляет более 1000 значков в виде шрифта Segoe MDL2 Assets. Получить значок из шрифта может быть не так просто, но наша технология отображения шрифта гарантирует, что эти значки будут выглядеть четко и резко на любом дисплее, при любом разрешении и в любом размере. Инструкции см. в разделе Значки Segoe MDL2.
Использование шрифта.
Вам не обязательно использовать шрифт Segoe MDL2 Assets, вы можете выбрать любой шрифт, установленный пользователем в системе, например Wingdings или Webdings.
Использование SVG-файла векторной графики.
Ресурсы SVG идеально подходят для значков, потому они всегда четко выглядят при любом размере или разрешении. Большинство приложений для рисования поддерживает экспорт в SVG-файлы. Инструкции см. в разделе SVGImageSource.
Использование объектов Geometry.
Подобно SVG-файлам геометрии являются векторными ресурсами, поэтому они всегда выглядят четко. Однако создать геометрию не так просто, так как вам необходимо отдельно указать все точки и кривые. Этот вариант следует использовать, только если вам нужно изменить значок во время выполнения приложения (например, для анимации). Инструкции см. в разделе Синтаксис команд перемещения и рисования.
Вы также можете использовать растровое изображение (например, в формате PNG, GIF и JPEG), хотя это не рекомендуется.
Растровые изображения создаются в определенном размере, поэтому их необходимо масштабировать в зависимости от требуемого размера значка и разрешения экрана. При уменьшении (сжатии) размера значка он может оказаться размытым. При увеличении размера он может стать угловатым и пикселизированным. Если вам необходимо использовать растровое изображение, рекомендуется формат PNG или GIF, а не JPEG.
Привязка функции к значку
После создания значка следующим шагом является привязка к нему команды или действия перехода. Для этого рекомендуется добавить значок на кнопку или панель команд.
Можно также анимировать значок, чтобы привлечь внимание к компоненту пользовательского интерфейса, например к кнопке «Далее» в учебнике, или просто отразить действие, связанное со значком, в развлечениях и интересных способах. См. аниматедикон.
Создание кнопки значка
Значок можно поместить на стандартную кнопку. Так как кнопки можно использовать в различных местах, это дает больше гибкости при выборе расположения значка.
Вот несколько способов добавления значка на кнопку.
Шаг 2.
Можно использовать один из объектов элементов Icon: BitmapIcon, фонтикон, пасикон, имажеиконили симболикон. Это позволяет получить более широкий выбор значков и объединять разные значки и другие типы содержимого, например текст.
Создание серии значков на панели команд
Если у вас есть несколько похожих команд, таких как вырезать, скопировать и вставить, или набор команд рисования для программы редактирования фотографий, объедините их на панели команд. На панели команд размещается одна или несколько кнопок панели приложения или кнопок-переключателей панели приложения, каждая из которых представляет действие. У каждой кнопки есть свойство Icon, которое используется для выбора отображаемого значка. Существует множество способов указать значок.
Проще всего использовать список стандартных значков, которые предоставляем мы, — просто укажите имя значка, например «Назад» или «Стоп», и система его нарисует.
Полный список имен значков см. в разделе Перечисление Symbol.
Существуют и другие способы указания значков для кнопок на панели команд:
Дополнительные сведения о панелях команд см. в статье, посвященной панели команд.
Настройка значка для приложения wpf (VS 08)
прежде чем идти дальше, я упомяну, что я пробовал решения в следующее:
Как установить значок для моего приложения в visual studio 2008?
установить значок приложения из ресурсов в VS 05
Я пытаюсь установить значок для моего приложения.
AFAIK, мне нужно потенциально 3 изображения?
Так что все в порядке.
теперь я выбрал значок. Как использовать его в одной из вышеперечисленных ситуаций?
Я попытался добавить его в ресурсы, ничего не происходит. Следуя этому первому решению SO,
представление ресурсов пусто, и я не могу щелкнуть правой кнопкой мыши в этом представлении.
Если я щелкните правой кнопкой мыши на решении > свойства > ресурсы > я могу добавить изображение значка, но он не отображается ни в одном из перечисленных выше мест. (или где-нибудь, что я могу видеть)
1) Как установить значок приложения для приложения WPF?
5 ответов
предполагая, что вы используете VS Express и C#. Значок устанавливается на странице «свойства проекта». Чтобы открыть его, щелкните правой кнопкой мыши имя проекта в обозревателе решений. на открывшейся странице есть вкладка приложение, на этой вкладке вы можете установить значок.
@742 ответ работает довольно хорошо, но, как указано в комментариях при запуске из отладчика VS, общий значок все еще отображается.
Если вы хотите иметь свой значок, даже когда вы нажимаете F5, вы можете добавить в главном окне:
(обратите внимание, что вам все равно нужно будет установить значок приложения, или он все равно будет по умолчанию в Проводнике).
после получения XamlParseException сообщение: ‘Provide value on’ система.Окна.Бамл2006.TypeConverterMarkupExtension’ С данными решениями установка значка программно работала для меня. Вот как я это сделал:—5—>
Icon = new BitmapImage (новый Uri («icon_path>», UriKind.Родственник));
пожалуйста, сообщите мне, если у вас есть какие-либо трудности с реализацией этого решения, чтобы я мог помочь.