Создайте ссылку на Windows системный цвет (тип значения) с помощью конвертера в XAML - PullRequest
0 голосов
/ 03 февраля 2020

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

Например, у нас это есть в одной из наших тем XAML:

<Color x:Key="ButtonFaceColor">#FFD3D3D3</Color>

Затем на него ссылаются через ключ ресурса в различных частях XAML, в основном с кистями, но также с несколькими другими элементами, которые принимают цвет. Например, у нас может быть bru sh:

<SolidColorBrush x:Key="ButtonFaceBrush" Color="{StaticResource ButtonFaceColor}"/>

Однако, не только кисти используют цвета; у нас есть другие элементы, которые могут принимать цвета напрямую. По этой причине мы хотим настраивать использование цветов, а не кистей.

Теперь нам нужна тема, соответствующая теме Windows '. Если мы просто хотим использовать системный цвет как есть, мы можем изменить его на:

<StaticResource x:Key="ButtonFaceColor" ResourceKey="{x:Static SystemColors.ControlColor}"/>

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

<Binding x:Key="ButtonFaceColor" Source="{x:Static SystemColors.ControlColor}" Converter="{StaticResource RgbShadeConverter}" ConverterParameter="1"/>

Однако, тестируя даже с использованием только эталона цвета, как показано:

<Binding x:Key="ButtonFaceColor" Source="{x:Static SystemColors.ControlColor}"/>

Мы получаем ошибку, которая довольно непостижима. Судя по ошибкам, XAML пытается разрешить привязку, и, возможно, нам не понравится, что мы в основном заменяем Color структуру на Binding объект, который должен возвращать Color структуру ,

System.Windows.Markup.XamlParseException: 'Set property 'System.Windows.ResourceDictionary.DeferrableContent' threw an exception.' Line number '3' and line position '21'. ---> System.Xaml.XamlObjectWriterException: 'Provide value on 'MS.Internal.Markup.StaticExtension' threw an exception.' Line number '105' and line position '22'. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Infralution.Localization.Wpf, PublicKeyToken=547ccae517a004b5' or one of its dependencies. The system cannot find the file specified.

   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)

   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)

   at System.Reflection.Assembly.Load(AssemblyName assemblyRef)

   at System.Windows.Baml2006.Baml2006SchemaContext.ResolveAssembly(BamlAssembly bamlAssembly)

   at System.Windows.Baml2006.Baml2006SchemaContext.GetAssembly(Int16 assemblyId)

   at System.Windows.Baml2006.Baml2006SchemaContext.EnsureXmlnsAssembliesLoaded(String xamlNamespace)

   at System.Windows.Baml2006.Baml2006SchemaContext.GetXamlType(String xamlNamespace, String name, XamlType[] typeArguments)

   at MS.Internal.Xaml.XamlContext.GetXamlType(XamlTypeName typeName, Boolean returnUnknownTypesOnFailure, Boolean skipVisibilityCheck)

   at MS.Internal.Xaml.XamlContext.ResolveXamlType(String qName, Boolean skipVisibilityCheck)

   at MS.Internal.Xaml.Context.ObjectWriterContext.ServiceProvider_Resolve(String qName)

   at MS.Internal.Markup.StaticExtension.ProvideValue(IServiceProvider serviceProvider)

   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CallProvideValue(MarkupExtension me, IServiceProvider serviceProvider)

   --- End of inner exception stack trace ---

   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.CallProvideValue(MarkupExtension me, IServiceProvider serviceProvider)

   at System.Xaml.XamlObjectWriter.Logic_ProvideValue(ObjectWriterContext ctx)

   at System.Xaml.XamlObjectWriter.Logic_AssignProvidedValue(ObjectWriterContext ctx)

   at System.Xaml.XamlObjectWriter.WriteEndObject()

   at System.Xaml.XamlServices.Transform(XamlReader xamlReader, XamlWriter xamlWriter, Boolean closeWriter)

   at System.Windows.ResourceDictionary.EvaluateMarkupExtensionNodeList(XamlReader reader, IServiceProvider serviceProvider)

   at System.Windows.ResourceDictionary.GetKeyValue(KeyRecord key, IServiceProvider serviceProvider)

   at System.Windows.ResourceDictionary.SetKeys(IList`1 keyCollection, IServiceProvider serviceProvider)

   at System.Windows.Baml2006.WpfSharedBamlSchemaContext.<>c.<Create_BamlProperty_ResourceDictionary_DeferrableContent>b__297_0(Object target, Object value)

   at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst, XamlMember property, Object value)

   --- End of inner exception stack trace ---

   at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)

   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)

   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)

   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)

   at System.Windows.Application.LoadBamlStreamWithSyncInfo(Stream stream, ParserContext pc)

Что такое магическое заклинание, чтобы заставить XAML принять ссылку с преобразователем на тип значения вместо элемента Color?


ОБНОВЛЕНИЕ 1

Я также попробовал следующее:

<SolidColorBrush x:Key="ButtonFaceBrush" Color="{DynamicResource ButtonFaceColor}"/>

Это приводит к ошибке времени разработки:

An object of the type "System.Windows.Data.Binding" cannot be applied to a property that expects the type "System.Windows.Media.Color".

Что-то вроде того, почему Binding не сработал бы, я думаю. Изменение в:

<SolidColorBrush x:Key="ButtonFaceBrush" Color="{Binding ButtonFaceColor}"/>

исключает ошибку времени разработки. Однако при фактическом запуске приложения возникает то же исключение, о котором сообщалось изначально.

...