recursos dinámicos de nivel de aplicación no son dinámicas cuando alojada en ElementHost

StackOverflow https://stackoverflow.com/questions/727141

Pregunta

que celebro un control de usuario de WPF en un recipiente de Windows Forms. Ahora, quiero ser capaz de tema / piel del control de usuario. Para hacer esto, tengo varios diccionarios de recursos que definen las "pieles". Cuando mi aplicación se inicia creo una "nueva System.Windows.Application ()" para que Application.Current existe. Para cambiar el tema de la piel vieja se retira y una nueva piel se combina en el diccionario de recursos a nivel de aplicación en tiempo de ejecución. Sin embargo, esto no cambia ninguno de los recursos dyanamically que se hace referencia en el control de usuario. He intentado esto en una aplicación WPF recta y funcionó muy bien. Me estoy perdiendo algo, o no es posible hacer esto en absoluto? Por cierto, si añado una piel en los recursos de la aplicación antes de que se inicializa el control de usuario que va a funcionar, pero no puedo cambiar la piel después de eso.

Para repo esto de la manera más básica:

Crear una nueva aplicación de Windows Forms. Añadir un control de usuario de WPF a la aplicación. Esto es bastante simple:

<UserControl ...>
   <Grid>
      <Button
         Background="{DynamicResource ButtonBG}"/>
   </Grid>
</UserControl>

Cree dos ResourceDictionaries, White.xaml y Black.xaml (o lo que sea) que tienen un SolidColorBrush con el ButtonBG clave con el color correspondiente. En Form1.cs, agregue dos botones y una ElementHost. Ajuste el hijo del ElementHost a una instancia del control de usuario que acaba de crear. Cablear los botones para eventos que intercambian la piel:

private void White_Click(object sender, EventArgs e)
{
   Application.Current.Resources.MergedDictionaries[0] = 
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));
}

private void Black_Click(object sender, EventArgs e)
{
   Application.Current.Resources.MergedDictionaries[0] = 
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\Black.xaml", UriKind.Relative)));
}

En Program.cs, asegúrese de que Application.Current existe y establece la piel inicial:

[STAThread]
static void Main()
{
   new System.Windows.Application();

   Application.Current.Resources.MergedDictionaries[0] =
      (ResourceDictionary)Application.LoadComponent(
         new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));

   ...
}

Ahora, cuando se hace clic en el botón blanco que se puede esperar en el botón en el control de usuario a ponerse blanco y cuando se hace clic en el botón Negro Yo esperaría que el botón para encender negro. Esto no sucede, sin embargo.

¿Alguien sabe por qué? ¿Existe una solución?

Editar Idea:. Tal vez, si hay una manera de forzar la re-evaluación de DynamicResources cuando cambia el tema, que trabajarían

Gracias, Dusty

¿Fue útil?

Solución

Creo que esto puede ser un problema por alto en el marco de WPF.

Por lo que puedo decir a través del reflector, se observa que cuando el diccionario de recursos Application se cambia de manera catastrófica (un cambio que probablemente tendrá efectos como añadir, eliminar o reemplazar una piel de gran alcance), no hay código que se repite en toda del Windows en la aplicación y les obliga a volver a evaluar su DynamicResources. Sin embargo, otros elementos que considerarían de nivel superior en WPF como ElementHosts no reciben el mismo tratamiento. Esto lleva a la conducta que estoy experimentando.

Mi solución a este problema es ir manualmente a través de todos mis ElementHosts individualmente y añadir, quitar o reemplazar el archivo ResourceDictionary piel. No es perfecto, pero hace el trabajo.

Otros consejos

Otra solución sería la creación de una ventana maniquí y especificar el contenido de la ElementHost como contenido. Si nos fijamos en la aplicación y comprobar cómo se maneja cambios de resourcedictionaries, se ve que sólo se notifica ventanas ..

La única cosa que debe recordar es que nunca mostrar la ventana (-> excepción), y para cerrarla cuando se deshaga el ElementHost, por lo que el cierre de aplicaciones pueden correctamente

.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top