2009-08-04 14 views
41

Tengo una biblioteca, CommonLibraryWpfThemes, con varios archivos XAML del diccionario de recursos. El archivo My Themes/Generic.xml contiene una declaración ResourceDictionary.MergedDictionaries que combina todos los demás archivos.Problemas al hacer referencia a un diccionario de recursos que contiene un diccionario combinado

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, que tienen una referencia a CommonLibraryWpfThemes, y la referencia explícita 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. Me sale 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 el contenido de Generic.xaml en App.xaml directamente, todo funciona bien:

App.xaml - tiene éxito

<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 voy sobre esto en el camino equivocado. 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 varios 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.

EDIT:

Intenté envolver el ResourceDictionary en un elemento de ResourceDictionary.MergedDictionary, sino que también no funcionaba (me da 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> 
+1

Comenzaré una pequeña recompensa aquí. Combinar algunos RessourceDictionaries en un tema (y simplemente cargar esto en App.xaml) parece un escenario bastante común ... – Jens

Respuesta

4

Usted no debería tener para hacer referencia al generic.xaml, 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.

(EDIT para mayor claridad)

Una excepción a esto es la App.xaml, donde los recursos definidos sean accesibles por toda la aplicación, sin necesidad de hacer referencia a cualquier diccionario de recursos específicos. El recurso en sí, debería ser accesible por su nombre.

La razón por la que esto no

<Application.Resources> 
    <ResourceDictionary 
     Source="/CommonLibraryWpfThemes;component/Themes/Generic.xaml" /> 
</Application.Resources> 

es, creo, porque no se lo envuelve en una envoltura MergedDictionary, añadiéndolo a los diccionarios fusionadas. Agregar directamente a los recursos solo funciona para los recursos que declaras localmente, p. los estilos, etc. ellos mismos.

Sin embargo, como dije antes, no debería tener que combinar generic.xaml en cualquier lugar, tal vez debería simplemente refabricar 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 ser genéricos.xaml para tener un comportamiento de "estilo predeterminado": si un estilo con clave igual al tipo del elemento es accesible (globalmente o en recursos locales), luego usará el estilo como estilo predeterminado. El generic.xaml es solo una conveniencia.

Verificar this answer.

Para otros pinceles personalizados, etc., debe hacer referencia explícitamente a esos recursos.

También debe verificar el contenido del WindowDictionary.xaml, este error tiene un cierto olor al respecto.

+0

Así que creo que estás diciendo que hacer referencia a los ResourceDictionaries directamente en App.xaml es necesario y la única forma en que lo hará trabajo. Es decir., no hay forma de que pueda "precombinar" todos mis diccionarios y simplemente hacer referencia a la entidad precombinada desde App.xaml. No es tan conveniente, pero si así es como funciona, no es el fin del mundo. Hasta ahora, * siempre * configuré mis atributos de Estilos explícitamente usando '{StaticResource MyResourceName}', así que supongo que tendría que refactorizar muchas cosas para aprovechar el comportamiento predeterminado que permite Generic.xaml. ¿Tengo eso correcto? – devuxer

+0

Cuando combina diccionarios con app.xaml, hace que los recursos sean "globales", a los que puede acceder toda la aplicación (como su nombre lo indica). No es necesario hacer referencia a los recursos en app.xaml a través del nombre del diccionario, solo a través de la clave de recursos específicos, puede que no haya sido claro al respecto, aclararé la respuesta. Normalmente creo diccionarios fusionados agrupados para diferentes partes de la aplicación y hago referencia a ese diccionario en xaml según sea necesario. –

+0

Gracias por aclarar su respuesta, pero o estoy malinterpretando lo que quiere decir con "envolverlo en un contenedor 'MergedDictionary'" o eso tampoco funciona. Puse una edición en la parte inferior de mi pregunta con una muestra de código. – devuxer

12

Compruebe su constructor en App.xaml.cs llama InitializeComponent() - esto es lo que une los diccionarios de recursos ...

+2

Esto fue muy útil para mí. Estaba tratando de descubrir por qué mis páginas (alojadas en un marco) no obtenían el recursos definidos en mi App.xaml. Resulta que el constructor no estaba llamando a InitializeComponent. Gracias Chris !!!! – NathanAW

-1

Mi solución es here, haga clic Soluciones provisionales.

+1

Votado por: Enlace sin texto de enlace; sin explicación alguna; contenido externo: sin control sobre el contenido – trapicki

65

Respondí una pregunta similar aquí antes, vea Adding a Merged Dictionary to a Merged Dictionary pregunta.

Se trata de un error de optimización, consulte Microsoft Connect/DefaultStyleKey style not found in inner MergedDictionaries:

En la creación de cada objeto en XAML, si un estilo por defecto está presente (es decir, estilo w/una llave de tipo) que estilo debe se aplicado. Como puede imagine que hay varias optimizaciones de rendimiento para hacer que (implícita) busque un peso ligero como sea posible. Uno de ellos es que no miramos dentro Diccionarios de recursos a menos que estén marcados como "que contienen los estilos predeterminados". Hay un error: si todos sus estilos predeterminados están anidados en diccionarios fusionados de tres niveles profundos (o más profundo), el diccionario superior no se marca por lo que la búsqueda se salta. La solución alternativa es poner un estilo predeterminado a algo, cualquier cosa, en el diccionario raíz .

Así que 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> 
+0

El error solo parece estar presente en versiones anteriores de .NET 4: 4.0.30319.1008 específicamente. Lo he visto en XP y en algunas instalaciones de Windows 7 no actualizadas. –

0

que estaba recibiendo este error en mis pruebas de unidad y 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 se podí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.

Cuestiones relacionadas