wpf - Problemas para hacer referencia a un diccionario de recursos que contiene un diccionario combinado
wpf resourcedictionary (5)
Tengo una biblioteca, CommonLibraryWpfThemes, con varios archivos Resource Dictionary XAML. El archivo My Themes / Generic.xml contiene una declaración ResourceDictionary.MergedDictionaries que combina todos los demás archivos.
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
En mi proyecto de aplicación, tengo una referencia a CommonLibraryWpfThemes, y hago referencia explícita a Generic.xml en mi archivo App.xaml.
App.xaml - FALLA
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</Application.Resources>
</Application>
Esto no funciona Recibo el siguiente error cuando ejecuto mi aplicación:
System.Windows.Markup.XamlParseException occurred
Message="Cannot find resource named ''{_fadedOrangeBrush}''. Resource names are case sensitive. Error at object ''System.Windows.Setter'' in markup file ''CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml'' Line 18 Position 13."
Source="PresentationFramework"
LineNumber=18
LinePosition=13
Si coloco los contenidos de Generic.xaml en App.xaml directamente, todo funciona bien:
App.xaml - ÉXITOS
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/BrushDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/TextBlockDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/LabelDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/ButtonDictionary.xaml" />
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/ResourceDictionaries/WindowDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Tal vez estoy haciendo esto de la manera incorrecta. Mi objetivo es facilitar la referencia de todos los recursos de mi tema desde múltiples aplicaciones sin tener que enumerar todos los archivos individuales. ¿Hay una manera recomendada de hacer esto? (Nota: no estoy tratando de cambiar entre múltiples temas, solo tengo un tema).
Como beneficio adicional, sería bueno si alguien pudiera decirme cómo hacer referencia a recursos en una biblioteca externa sin romper el diseñador en Visual Studio.
Gracias.
EDITAR:
Intenté incluir ResourceDictionary en un elemento ResourceDictionary.MergedDictionary, pero tampoco funcionó (obtengo el mismo error):
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Comprueba tu constructor en llamadas a App.xaml.cs InitializeComponent (): esto es lo que combina los diccionarios de recursos ...
Estaba obteniendo este error en mis pruebas unitarias y la respuesta de Chris desde arriba me dio la pista que necesitaba. Básicamente en mi primer método probado, puse:
MyApplication.App app = new MyApplication.App();
app.InitializeComponent();
Y de repente podría encontrar mi plantilla para mis páginas. Nota: esto significa que debe verificar si ya existe una instancia de su Aplicación si también está probando su App.cs unitariamente.
Mi solución está here , haz clic en Soluciones provisionales.
No debería tener que hacer referencia a generic.xaml
en absoluto, tiene soporte incorporado. Sin embargo, esto significa que proporciona un estilo predeterminado, que no configura explícitamente. Los estilos / plantillas explícitamente establecidos deben poder obtenerse a partir de los diccionarios de res referenciados explícitamente.
(EDITAR para mayor claridad)
Una excepción a esto es App.xaml
, donde los recursos definidos son accesibles para toda la aplicación, sin necesidad de hacer referencia a ningún diccionario de recursos específico. El recurso en sí, debería ser accesible por su nombre.
La razón por la cual esto falla
<Application.Resources>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</Application.Resources>
es, creo, porque no lo MergedDictionary
en un contenedor MergedDictionary
, y lo agregó a los diccionarios fusionados. Agregar directamente a los recursos funciona solo para los recursos que declara localmente, por ejemplo, los estilos, etc.
Sin embargo, como dije antes, no debería tener que fusionar generic.xaml
cualquier lugar, tal vez solo debería refactorizar pinceles y otros recursos usados fuera de los estilos, y fusionar solo esos recursos en app.xaml
.
También tenga en cuenta que los estilos no tienen que estar en generic.xaml para tener un comportamiento de "estilo predeterminado": si un estilo con clave igual al tipo del elemento es accesible para él (globalmente, o en recursos locales), entonces usará el estilo como un estilo predeterminado. El generic.xaml
es solo una conveniencia.
Verifica this respuesta.
Para otros pinceles personalizados, etc., debe hacer referencia a esos recursos explícitamente.
También debe verificar el contenido de WindowDictionary.xaml
, este error tiene cierto olor al respecto.
Respondí una pregunta similar aquí anteriormente, vea Agregar un diccionario fusionado a una pregunta del Diccionario combinado .
Este es un error de optimización, vea el estilo Microsoft Connect / DefaultStyleKey no encontrado en los MergedDictionaries internos :
En la creación de cada objeto en XAML, si está presente un estilo predeterminado (es decir, estilo con una clave de Tipo), se debe aplicar ese estilo. Como se puede imaginar hay varias optimizaciones de rendimiento para hacer que la búsqueda (implícita) sea lo más ligera posible. Una de ellas es que no buscamos los Diccionarios de recursos a menos que estén marcados como "que contienen estilos predeterminados". Hay un error: si todos sus estilos predeterminados están anidados en diccionarios combinados de tres niveles (o más profundos), el diccionario superior no se marca, por lo que la búsqueda se salta. La solución alternativa es poner un estilo predeterminado en algo, cualquier cosa, en el diccionario raíz.
Entonces, agregar un estilo ficticio al diccionario raíz corrige esto. Ejemplo
<Application x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Dummy Style, anything you won''t use goes -->
<Style TargetType="{x:Type Rectangle}" />
</ResourceDictionary>
</Application.Resources>
</Application>