|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Создаю я какой-то настраиваемый элемент и прописываю ему шаблон. Куда и как лучше этот шаблон записать? И потом его подключить так чтобы он работал аналогично дефолтным шаблонам стандартных элементов. Объясню на примере стиля для TextBlock Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
Первый TextBlock просто выводится с указанным дефолтным стилем. Во втором, явно изменяется цвет текста. В третьем, цвет текста задаётся из стиля самого элемента и, естественно, внешний стиль не учитывается - фон и Margin сброшены до дефолтных значений. В четвёртом, в стиле элемента явно ссылаюсь на внешний стиль. Но как работают дефолтные шаблоны, какой у них механизм? Дефолтный шаблон это же тоже какой-то стиль заданный на каком-то уровне. Но при задании стиля в элементе мне же не надо явно на него ссылаться, но тем не менее, все значения для других свойств берутся из этого дефолтного шаблона. А для моего кастомного так не получается сделать. Или все эти значения по умолчанию задаются при инициализации DP свойств элементов? И стили на них не влияют? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2020, 16:54 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Eld Hasp Но при задании стиля в элементе мне же не надо явно на него ссылаться Можно и сослаться - для этого у стиля есть свойство BasedOn. Eld Hasp но тем не менее, все значения для других свойств берутся из этого дефолтного шаблона А в отсутствие BasedOn работает всё тот же механизм resources lookup - выполняется поиск стиля по ключу, которым является тип элемента. Eld Hasp Или все эти значения по умолчанию задаются при инициализации DP свойств элементов? И стили на них не влияют? Еще как влияют. Дефолтный шаблон может быть гораздо сложнее, чем просто задание фона или цвета, и все эти сложности просто технически невозможно описать в инициализаторах DP. В общем, гуглите по слову generic.xaml. Вот простейший пример (в разделе Solution 3). ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2020, 17:33 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, спасибо! Постараюсь разобраться! ... |
|||
:
Нравится:
Не нравится:
|
|||
19.01.2020, 22:49 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
a) разберитесь в том, как устроена иерархия ресурсов <ResourceDictionary/>, на "физическом уровне" методом объединения <ResourceDictionary.MergedDictionaries/>, так и на уровне логического и визуального дерева. б) как устроено статическое и динамическое связывание. Как осуществляется поиск ресурсов по ключу. Так можно будет переопределить цвет рамки элемента управления не только через переопределение стиля, но и через ресурсу. в) используйте динамическое связывание с ресурсами "{DynamicResouce ResourceName}" для ресурсов стиля, локализации, других элементов которые могут изменится в процессе работы. Особенно к глобальному переопределению. Очень хорошо подходит для этого локализация и стилизация приложения. г) значением {Static и DynamicResouce {Значение}} может быть, что угодно, это может быть любой объект CLR, включая Type. Часто используют в качестве ключа статический свойства, такие поля заканчиваются на Key или вроде того, что может быть удобно для рефакторинга, но возни больше д) в шаблоне старайтесь использоваться TemplateBinding для связывания полей внутренних элементов с полями самого элемента. Тогда будет возможность через стили управлять видом элемента. Определить стиль по умолчанию, это будет тот стиль который определен с ключём {x:Type ControlType}, в текущем контексте, проще говоря, что найдется первым. Если сделать через Generic.xaml, всё будет удобно, так как этот файл подгружается в ресурсы "автоматически" значит будет ситуации при которой стиль для элемента управления не определен вообще. е) есть еще StateManager у контролов, он довольно удобен в плане визуализации элемента управления, но он в любом случае завязан на ресурсы. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2020, 12:13 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Roman Mejtes a) разберитесь в том, как устроена иерархия ресурсов <ResourceDictionary/>, на "физическом уровне" методом объединения <ResourceDictionary.MergedDictionaries/>, так и на уровне логического и визуального дерева. б) как устроено статическое и динамическое связывание. Как осуществляется поиск ресурсов по ключу. Раньше об этом не задумывался. Знаний не хватало и на гораздо более простые вещи. Сейчас стало интересным и с этим разобраться. Можете подсказать ресурс где это доступно описано? Roman Mejtes б) ...Как можно будет переопределить цвет рамки элемента управления не только через переопределение стиля, но и через ресурсу. Разве сейчас это возможно? Или я не так что-то делаю. Вроде, изменение вида элемента через системные ресурсы было возможно в Win 7. А начиная с Win 8 или 8.1 были изменены шаблоны элементов и теперь все цвета прописываются константами в самом шаблоне. Пример http://www.cyberforum.ru/blogs/1297115/blog5553.html Или вы нечто иное имели ввиду? Roman Mejtes в) используйте динамическое связывание с ресурсами "{DynamicResouce ResourceName}" для ресурсов стиля, локализации, других элементов которые могут изменится в процессе работы. Особенно к глобальному переопределению. Очень хорошо подходит для этого локализация и стилизация приложения. Да, в своих элементах так и делаю. Но в в дефолтных шаблонах в большинстве случаев используется StaticResource. Иногда только из-за этого приходится заменять шаблоны - получаю дефолтный, заменяю Static на Dynamic и использую. Roman Mejtes г) значением {Static и DynamicResouce {Значение}} может быть, что угодно, это может быть любой объект CLR, включая Type. Часто используют в качестве ключа статический свойства, такие поля заканчиваются на Key или вроде того, что может быть удобно для рефакторинга, но возни больше Это знаю и иногда использую. Как я понимаю, Resource - это (почти) Dictonary <object,object>. И пользоваться им можно почти так же. Не совсем понятен механизм наследования по визуальному и логическим деревьям. С этим только пытаюсь разобраться. Roman Mejtes д) в шаблоне старайтесь использоваться TemplateBinding для связывания полей внутренних элементов с полями самого элемента. Тогда будет возможность через стили управлять видом элемента. Определить стиль по умолчанию, это будет тот стиль который определен с ключём {x:Type ControlType}, в текущем контексте, проще говоря, что найдется первым. Если сделать через Generic.xaml, всё будет удобно, так как этот файл подгружается в ресурсы "автоматически" значит будет ситуации при которой стиль для элемента управления не определен вообще. TemplateBinding использую. Не понятно как правильно компоновать свои элементы. На данном этапе делаю это как xaml+xaml.cs. И прописываю шаблон элемента сразу в xaml. Пришёл к тому, что это в о многих случаях делает элемент неудобным для использования. Задумался над тем, что логику с добавлением свойств, их обработки, методами надо делать отдельным классом на C#, а не частичным в CB XAML. Но куда тогда записать шаблон элемента, чтобы он автоматически подхватывался в любой части приложения? Из попыток найти решение и создал тему. Generic.xaml ? - буду разбираться. Roman Mejtes е) есть еще StateManager у контролов, он довольно удобен в плане визуализации элемента управления, но он в любом случае завязан на ресурсы. Тоже - буду разбираться. Спасибо, за развёрнутый ответ! ... |
|||
:
Нравится:
Не нравится:
|
|||
20.01.2020, 18:49 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Eld Hasp Roman Mejtes a) разберитесь в том, как устроена иерархия ресурсов <ResourceDictionary/>, на "физическом уровне" методом объединения <ResourceDictionary.MergedDictionaries/>, так и на уровне логического и визуального дерева. б) как устроено статическое и динамическое связывание. Как осуществляется поиск ресурсов по ключу. Раньше об этом не задумывался. Знаний не хватало и на гораздо более простые вещи. Сейчас стало интересным и с этим разобраться. Можете подсказать ресурс где это доступно описано? https://docs.microsoft.com/en-us/dotnet/desktop-wpf/fundamentals/xaml-resources-define в частности, подразделы Static resource lookup behavior и Dynamic resource lookup behavior ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2020, 06:21 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Eld Hasp Не понятно как правильно компоновать свои элементы. На данном этапе делаю это как xaml+xaml.cs. И прописываю шаблон элемента сразу в xaml. Пришёл к тому, что это в о многих случаях делает элемент неудобным для использования. Задумался над тем, что логику с добавлением свойств, их обработки, методами надо делать отдельным классом на C#, а не частичным в CB XAML. Но куда тогда записать шаблон элемента, чтобы он автоматически подхватывался в любой части приложения? Из попыток найти решение и создал тему. Generic.xaml ? - буду разбираться. лично я не использую UserControl'ы с CodeBehind файлами, но это дело добровольное, они же ни кому не мешают, по сути и ни кто не заставляет реализовывать в них логигу. для компоновки элементов управления я использую DataTemplate'ы, которые погоняют другими DataTemplate'ами, в результате я просто указываю какую модель нужно отобразить в главном окне и программа запускается. Окно само находит нужный шаблон для заданной модели представления через DataTemplateSelector'ы. А все компоненты просто раскиданы по DataTemplate'ам всё это относится именно к компоновке, элементов управления. Если же я делаю свой элемент управления, я делаю следующим образом: 1. Создаю сборку для элементов управления WPF 2. Создаю новый класс и наследую его от Control или ContentControl, ItemsControl, ListBox в зависимости от типа объекта и его поведения (не внешнего вида, а именно поведения). (Если это списочный элемент управления с вложенными элементами, то очевидно, что наш выбор ItemsControl и ListBox, а если, к примеру, я хочу сделать ComboBox с древовидной структурой я буду наследовать ListBox или TreeView, хоть их внешний вид и не похож на ComboBox, но это не важно, важно, что его поведение соответствует моим желаниям. 3.После того как создали новый тип и наследовали его от Control нужно переопределить в нём ключ стиля по умолчанию, для данного элемента, так как он наследуется от базового (этого можно и не делать, если вы не планируйте менять внешний вид элемента) Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
4. Затем создаем папку Themes, а в проекте, в папке файл Generic.xaml, так же создаю справочник конкретно для моего контрола с понятным названием типа MyUserControlDefaultStyle.xaml и делаю её "импорт" (Merge) в Generic.xaml Themes\Generic.xaml Код: xml 1. 2. 3. 4. 5.
обычно в качестве источника я указываю полный путь до файла, относительные пути ппц капризные, особенно это актуально, когда этих справочников дофигища в разных сборках еще могут быть и т.д. ну и пихать всё в Generic.xaml плохая идея. 1 элемент управления, это минимум один файл с ресурсами подключенный в нужном месте. 5. Внутри файла MyUserControlDefaultStyle.xaml определяем шаблон нашего элемента и его стиль по умолчанию, именно стиль по умолчанию будет определять шаблон по умолчанию, по этому для него мы создаем какой нибудь произвольный ключ MyUserControlDefaultStyle.xaml: Код: xml 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29.
вот собственно и всё, теперь осталось подключить эту сборку в ваше приложение и разместить в окне элемент управления MyUserControl, всё остальное будет работать само, а если вы определите стиль в своей сборке с ключом {x:Type MyUserControl} он объединиться с дефолтным. 6. Часто бывает так, что необходимо взаимодействовать с частями элемента управления, то есть его внутренними компонентами. Можно попытаться найти их в визуальном дереве, но это плохой метод. Лучше воспользоваться атрибутом [TemplatePart(Name = "PART_ControlName", Type = typeof(ControlType) )], определить элемент управления в шаблоне с таким именем, в примере выше он уже определен как PART_Cube. Важно помнить один момент, объект может до конца загрузиться, когда вы попытаетесь найти этот элемент, то есть сам элемент может существовать, но его содержимое нет (шаблон еще не применялся). По этому искать этот внутренний элемент лучше всего в методе void OnApplyTemplate(), этот метод построит визуальное дерево на основе шаблона и вы практически гарантированно найдете этот элемент, если он определен Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31.
Важно не путать компоновку элементов управления и шаблоны элементов управления. Сам элемент управления это объект в котором определили некую логику работы и внешнее отображение элемента зависит от внутреннего состояния. Сам элемент управления (создаваемый вами) не должен ничего знать о модели представления, он должен быть абстрагирован от неё и работать только на основе своих свойств зависимостей. Внутри шаблона мы можем использовать связывание только в рамках самого элемента, шаблонное связывание или, в плохом случае, с другими элементами входящими в визуальное дерево, но не с контекстом данным. А вот DataTemplate даже имеет свойство DataType в котором вы указывайте тип модели представления которую он отображает, следовательно он связан с моделью представления, в нём можно задать все связывания и DataTrigger'ы. В результате в шаблоне данных вы компонуете объекты и связывайте свойства элементов управления и свойства модели представления. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2020, 12:30 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Roman Mejtes 3.После того как создали новый тип и наследовали его от Control нужно переопределить в нём ключ стиля по умолчанию, для данного элемента, так как он наследуется от базового (этого можно и не делать, если вы не планируйте менять внешний вид элемента) Код: c# 1. 2. 3. 4. 5. 6. 7. 8.
Это рекомендуется делать в статик-конструкторе. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2020, 12:33 |
|
Создание глобальных стилей, шаблонов (темы)
|
|||
---|---|---|---|
#18+
Сон Веры Павловны, ага :( вот, что значит отсутствие практики ... |
|||
:
Нравится:
Не нравится:
|
|||
21.01.2020, 12:36 |
|
|
start [/forum/topic.php?fid=21&msg=39916133&tid=1440296]: |
0ms |
get settings: |
10ms |
get forum list: |
13ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
34ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
44ms |
get tp. blocked users: |
1ms |
others: | 11ms |
total: | 132ms |
0 / 0 |