c# wpf xaml shared-libraries resourcedictionary

c# - ¿Hay alguna forma de usar StaticResource en una biblioteca de control de WPF y poder ver en tiempo de diseño?



xaml shared-libraries (3)

Aquí está mi solución parcial a su problema. No he intentado manejar recursos sueltos, pero tengo cierto éxito compartiendo recursos entre WinForms y WPF.

  • Cree una biblioteca de clase para contener sus recursos en archivos .ResX (por ejemplo, Resources.resx, Resources.fr.resx, etc.)
  • Cree sus controles WPF en una biblioteca de control de usuario de WPF
  • Crea tu host WinForms
  • Infralution.Localization.Wpf referencia a los recursos en su biblioteca de recursos de WPF usando la extensión de marcado Infralution.Localization.Wpf y el administrador de cultura, por ejemplo

    <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/>

  • Coloque el contenido de los controles de usuario de WPF en uno o más diccionarios de recursos como plantillas de control, e, g

    <ControlTemplate x:Key="TestTemplate"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock Text="{Resx ResxName=ResourceLib.Resources, Key=Test}"/> </Grid> </ControlTemplate>

  • Usa la plantilla de recursos en tus controles de usuario

    <UserControl x:Class="WpfControls.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" > <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="ResourceDictionary.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> <ContentControl Template="{StaticResource TestTemplate}" /> </UserControl>

  • Agregue un par de líneas de código para que las cosas funcionen

    public partial class UserControl1 : UserControl { // we require a reference to the resource library to ensure it''s loaded into memory private Class1 _class1 = new Class1(); public UserControl1() { // Use the CultureManager to switch to the current culture CultureManager.UICulture = Thread.CurrentThread.CurrentCulture; InitializeComponent(); } }

Aquí hay una aplicación de demostración simple llamada WindowsFormsHost.7z

Tengo una Biblioteca de control de WPF que se agrega a una aplicación de formularios de Windows. Queremos permitir que los controles sean localizables, sin embargo, no estoy seguro de cómo HACERLO COMPLETAMENTE sin duplicar el código. Esto es lo que estoy haciendo ahora .

Básicamente, en la aplicación Windows forms, antes de que la aplicación principal comience, estoy instanciando un App.xaml que se encuentra dentro de la aplicación de formularios (que contiene mis enlaces a mis recursos que también viven en la aplicación de formularios). Esto funciona perfectamente para el tiempo de ejecución.

Sin embargo, mis controles de usuario tienen Content="{StaticResource SomeVariableName}" , que terminan en blanco. Puedo solucionar esto teniendo un app.xaml y diccionarios de recursos apropiados en mi biblioteca de control que coincidan con los de mi aplicación de formularios de Windows. Sin embargo, este es un código duplicado.

Cosas que ya he intentado en vano:

  • Crea una instancia del App.xaml que vive dentro de la biblioteca de control de usuarios desde mi aplicación de formularios. Esto no funciona porque los URI de mis recursos están buscando un recurso incrustado, no mi diccionario de recursos local (podría simplemente copiar los archivos de recursos del control a una ubicación adecuada dentro de mi aplicación de formularios en la compilación). ¿Podría aprovechar DeferrableContent aquí? Sin embargo, no hay mucho en línea en lo que pude encontrar sobre este atributo y cómo debería usarse.
  • Me gustaría utilizar construcciones posteriores para la aplicación y los diccionarios, sin embargo, la instanciación de la aplicación es una referencia estática de una App.xaml compilada por lo que yo sé. Por lo tanto, App.xaml debe vivir dentro de la forma al menos
    • Intenté tener un App.xaml duplicado con una compilación posterior moviendo el recursoourictionary.xaml. Pensé que una aplicación duplicada.xaml está bien, ya que esa es la fuerza impulsora y es posible que no desee confiar en una del control de todos modos (que da vueltas atrás y hace que se pregunte si debería tener entonces el App.xaml en el control de a menos que quiera permitir un valor predeterminado que usa recursos incrustados ...) Eso también falló al decir que no podía encontrar el recurso a pesar de que se ubicó donde el URI debería haber estado apuntando. El código descompilado apunta a Uri resourceLocater = new Uri("/WindowsFormsApplication3;component/app.xaml", UriKind.Relative);

Entonces, ¿hay alguna manera de permitir que esto funcione Y tener un tiempo de diseño de los valores predeterminados de los componentes Y evitar la duplicación? O bien, ¿la duplicación está bien en este caso? Si el subartículo de mi segunda viñeta parece estar bien (App.xaml duplicado con recursos de compilación copiados), ¿cómo hago para que no busque un elemento de nivel de componente, sino un nivel de archivo uno?

Última pregunta (y puedo publicar esto por separado si es necesario) que acabo de prestar atención. Mi App.xaml se está integrando en el código, por lo que no me permite crear nuevos ResourceDictionaries sobre la marcha de todos modos. ¿Hay alguna manera de hacer esto?

Opción final ... ¿posiblemente la mejor? - Planeo usar el código de Andre van Heerwaarde de todos modos , entonces ¿debería simplemente verificar la existencia de un archivo y agregarlo como un recurso combinado sobre la marcha? Básicamente, tengo un App.xaml en mi control de usuario que enlaza con un ResourceDictionary incrustado por defecto. Y, luego, haga que el código busque los recursos localizados apropiados sobre la marcha, que pueden ser rutas de archivos relativas. El único inconveniente que veo aquí es que el valor predeterminado no se puede cambiar sobre la marcha ... que probablemente podría incluso tener esa apariencia en un lugar específico (utilizando algún tipo de convención) y tener esa preferencia sobre la incorporada?

Ah, y mi razón para no querer recursos incrustados es que los usuarios finales puedan agregar / modificar nuevos recursos localizados después de desplegar la compilación.

Puedo agregar código si te ayuda a visualizar esto mejor, solo házmelo saber.

ACTUALIZAR

Ahora me encuentro con un problema adicional con el estilo y no solo con la localización.

Aquí hay un ejemplo de uno de los botones internos en uno de los controles:

<Button Style="{StaticResource GrayButton}"

Algunas cosas más que intenté / pensé:

  • No puedo crear una aplicación.xaml (que nunca se usaría) con la configuración de ResourceDictionary ya que las definiciones de aplicación no están permitidas en los proyectos de la biblioteca. Podría incorporar esto en los recursos del control, pero eso siempre tendría prioridad sobre cualquier recurso de nivel de aplicación y perdería la personalización.

Aquí hay un caso de conexión que realmente suena como lo que estoy buscando, sin embargo, no proporciona ninguna solución real a este

La solución (más allá de la cima ... que no funciona) en la que puedo pensar que podría funcionar (y aún no lo he intentado) también parece mucho trabajo para algo que creo que debería ser simple. Pero, podría ser capaz de crear algunas propiedades de dependencia en el control al que pueda enlazar y luego permitir que el proyecto que va a utilizar el control lo sobreescriba. Como dije, parece mucho trabajo para una solicitud bastante simple :). ¿Esto funcionaría? Y más importante, ¿hay una solución mejor y más simple que me falta?


Me he encontrado con este problema una vez, y lo resolví dejando caer todo el asunto "Los recursos son objetos indexados por clave en diccionarios canónicos".

Quiero decir, el simple hecho de definir un recurso en un proyecto y hacer referencia a él en otro por su "clave" debería dar escalofríos a cualquier persona en su sano juicio. Yo quería referencias fuertes .

Mi solución a este problema fue crear una herramienta personalizada que convierta mis archivos xaml de recursos en clases estáticas con una propiedad para cada recurso:

Entonces MyResources.xaml:

<ResourceDictionary> <SolidColorBrush x:Key="LightBrush" ... /> <SolidColorBrush x:Key="DarkBrush" ... /> </ResourceDictionary>

Se convierte en MyResources.xaml.cs

public static class MyResources { static MyResources() { // load the xaml file and assign values to static properties } public static SolidColorBrush LightBrush { get; set; } public static SolidColorBrush DarkBrush { get; set; } }

Para hacer referencia a un recurso, puede usar x:Static lugar de StaticResource :

<Border Fill="{x:Static MyResources.LightBrush}" BorderBrush="{x:Static MyResources.DarkBrush}" ... />

Ahora tiene referencias sólidas, autocompletado y verificación de recursos en tiempo de compilación.


Yo también tuve un problema al tratar temas de estilo y recursos estáticos disponibles. Entonces, creé una biblioteca independiente que básicamente no tenía nada más que los temas que se utilizarían, todos anidados como los recursos FUSIONADOS de su pregunta vinculada anterior.

Luego, en el formulario de Windows (.xaml), puse referencia a esa biblioteca, algo así como

<Window x:Class="MyAppNamespace.MyView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" ... /> <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <!-- Common base theme --> <ResourceDictionary Source="pack://application:,,,/MyLibrary;component/Themes/MyMainThemeWrapper.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <Rest of XAML for the WPF window> </Window>

El "componente" parece referirse a la raíz del proyecto dado "MyLibrary". En el proyecto real, creé una subcarpeta llamada "Temas", por lo tanto, la fuente incluye ...; componente / Temas / ...

El "MyMainThemeWrapper.xaml" es muy parecido a sus diccionarios de recursos combinados anidados, y lo ve todo perfectamente desde otras bibliotecas.