c# - tutorial - Estilos de todo el ensamblado/nivel raíz en la biblioteca de clases WPF
wpf introduccion (6)
Tengo un ensamblado de biblioteca de clase C # (2008 / .NET 3.5) que admite WPF (basado en este artículo ).
Creé varias ventanas y ahora intento crear un conjunto de estilos común para ellas. Sin embargo, como es una biblioteca de clases (en lugar de una aplicación WPF), no tengo un app.xaml (y su Aplicación contenida y los Application.Resources correspondientes) en los que almacenar estos estilos para el acceso global.
Entonces, ¿cómo puedo crear un conjunto de definiciones de estilo de primer nivel que serán vistas por todos los archivos xaml en el ensamblado, dado que no tengo app.xaml (ver arriba) ? ¿Y / o es posible agregar una app.xaml funcional a una biblioteca de clases?
FYI, intenté crear un ResourceDictionary en un archivo ResourceDictionary.xaml e incluirlo en cada ventana dentro de un bloque "Window.Resources". Eso resultó para resolver el estilo de los botones, etc ... pero no para la ventana que los rodea. Puedo poner Style="{StaticResource MyWindowStyle}"
en el bloque de apertura de la ventana, y se compila y se muestra en la ventana VS Design bien, pero durante el tiempo de ejecución real obtengo una excepción de análisis (MyWindowStyle no se pudo encontrar; estoy adivinando Visual Studio ve el diccionario incluido después de la línea en cuestión, pero la CRL hace las cosas más secuencialmente y, por lo tanto, aún no ha cargado el ResourceDictionary).
Gracias por las ideas, pero aún no se van ... aparentemente una biblioteca de clases NO admite el uso de generic.xaml implícitamente. Agregué generic.xaml a mi proyecto de biblioteca de clase y configuré su Acción de compilación en "Recurso". Contiene:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Window}" x:Key="MyWindow">
<Setter Property="Background" Value="Black"/>
</Style>
</ResourceDictionary>
La ventana xaml que quiero que use el tema se ve así:
<Window x:Class="MyAssembly.ConfigureGenericButtons"
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Style="{StaticResource MyWindow}"
Title="ConfigureGenericButtons">
...Buttons, etc...
</Window>
Aunque la ventana VS Design no muestra la ventana usando el estilo MyWindow (es decir, fondo negro), compila bien y se inicia. Sin embargo, cuando la aplicación que contiene esta biblioteca de clases realiza una llamada que hace que aparezca esta ventana, obtengo una XamlParseException:
No se puede encontrar el recurso llamado ''{MyWindow}''.
También traté de omitir el parámetro Estilo, para ver si la ventana usaría el estilo de forma predeterminada (y lo intenté con la clave x: en genérico.xaml incluido y sin). No hay errores, pero cualquier cosa definida en generic.xaml tampoco apareció.
¿Estoy haciendo algo mal aquí, o alguna otra idea sobre cómo se pueden usar estilos personalizados comunes en una ventana (es decir, no es necesario definir los estilos en cada ventana xaml), con la advertencia de que NO es un ¿solicitud?
El Dr. WPF (o la persona conocida anteriormente como Dr. WPF) tiene una excelente post sobre el tema.
Aquí hay un extracto de la publicación donde crean el objeto Aplicación y añaden recursos:
if (Application.Current == null)
{
// create the Application object
new Application();
// merge in your application resources
Application.Current.Resources.MergedDictionaries.Add(
Application.LoadComponent(
new Uri("MyLibrary;component/Resources/MyResourceDictionary.xaml",
UriKind.Relative)) as ResourceDictionary);
}
Dado que mi ensamblado se aloja a través de la interoperación, tuve que agregar la configuración de ShutdownMode de la siguiente manera y el cierre cuando finalice:
new Application() { ShutdownMode = ShutdownMode.OnExplicitShutdown };
Funcionó a las mil maravillas.
Entonces, después de pasar mucho tiempo, finalmente descubrí esto. Así es cómo:
- En la biblioteca de controles de WPF, agregue una nueva carpeta llamada
themes
. - Dentro de la carpeta de
themes
, agregue un diccionario de recursos llamadogeneric.xaml
. Dentro de
generic.xaml
, agregue su recurso con la siguiente sintaxis:<SolidColorBrush x:Key="{ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}" Color="Blue" />
En su control, use la siguiente sintaxis para acceder a este recurso:
Background="{StaticResource {ComponentResourceKey {x:Type local:UserControl1}, MyEllipseBrush}}"
Cosas a tener en cuenta:
- Los pasos 1 y 2 normalmente los hace automáticamente Visual Studio cuando crea una nueva Biblioteca de controles de WPF.
- No entiendo completamente el propósito del primer parámetro de
ComponentResourceKey
, pero es obligatorio. Use el nombre del control que consumirá este recurso. - El diseñador de Visual Studio no pudo ubicar el recurso en mi caso. Podría ser un problema de caché, no estoy seguro. Sin embargo, en tiempo de ejecución funciona bien.
- Puede leer más detalles sobre esta sintaxis en este artículo de MSDN .
Espero que esto haga algunas vidas más fáciles.
Esto suena como un trabajo para temer.
- Agregue un
/themes/generic.xaml
ResourceDictionary a su proyecto. - Agregue lo siguiente a AssemblyInfo.cs:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
- ?
- ¡Lucro!
Cualquier recurso que agregue a genérico será utilizado por todos los controles. También puede crear temas específicos de perfil (Luna, Aero, etc.) incluyendo un archivo ResourceDictionary con el nombre de tema correcto en el directorio de themes
.
Aquí hay un enlace para obtener más información: crear y aplicar temas personalizados
Prueba agregar
Style={DynamicResource MyStyle}
No puede usar un StaticResource en este caso.
Si no tiene un app.xaml, aún puede cargarlo en los recursos de nivel de aplicación, pero tiene que escribir código (no xaml) para hacerlo, similar a esto ...
void LoadIt()
{
ResourceDictionary MyResourceDictionary = new ResourceDictionary();
MyResourceDictionary.Source = new Uri("MyResources.xaml", UriKind.Relative);
App.Current.Resources.MergedDictionaries.Add( MyResourceDictionary )
}
echa un vistazo a este sitio para ver un ejemplo: http://ascendedguard.com/2007/08/one-of-nice-features-about-wpf-is-how.html
si lo carga en Window.Resource, el diccionario solo está disponible para los niños de esa ventana. Debe tenerlo disponible para la ventana y sus hijos.
Intente cargarlo en su archivo app.xaml. Eso debería convertirlo en un recurso a nivel de aplicación, no en un recurso a nivel de ventana.