risorse a livello di applicazione dinamici non sono dinamici quando ospitati in ElementHost

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

Domanda

sto ospitando una WPF UserControl in un contenitore WinForms. Ora, voglio essere in grado di tema / pelle UserControl. Per fare questo, ho vari dizionari risorse che definiscono le "pelli". Quando la mia applicazione si avvia a creare una "nuova System.Windows.Application ()" in modo che Application.Current esiste. Per cambiare il tema della vecchia pelle viene rimosso e una nuova pelle viene unito il dizionario risorse a livello di applicazione in fase di esecuzione. Tuttavia, questo non cambia nessuna delle risorse dyanamically riferimento nel UserControl. Ho provato questo in un'applicazione dritto WPF e ha funzionato bene. Mi sto perdendo qualcosa, o non è possibile fare questo a tutti? A proposito, se posso aggiungere una pelle nelle risorse dell'applicazione prima che l'UserControl viene inizializzato che funzionerà ma non posso cambiare la pelle dopo.

Per repo questo nel modo più semplice:

Creare una nuova applicazione WinForms. Aggiungere un UserControl WPF per l'applicazione. Questo è abbastanza semplice:

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

Creare due ResourceDictionaries, White.xaml e Black.xaml (o qualsiasi altra cosa) che hanno un SolidColorBrush con la ButtonBG chiave con colore corrispondente. In Form1.cs, aggiungere due pulsanti e un ElementHost. Impostare il figlio della ElementHost a un'istanza di UserControl che abbiamo appena creato. Cablare i pulsanti per eventi che scambiano la pelle:

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)));
}

In Program.cs, verificare che Application.Current esiste e impostare la pelle iniziale:

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

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

   ...
}

Ora, quando il pulsante bianco viene cliccato mi aspetterei il pulsante nella UserControl a diventare bianchi e quando il tasto nero viene cliccato mi aspetto il pulsante per accendere nero. Questo non accade, tuttavia.

Qualcuno sa perché? C'è una soluzione?

Modifica Idea:. Forse, se c'è un modo per forzare una rivalutazione dei DynamicResources quando cambia il tema, che avrebbero lavorato

Grazie, Dusty

È stato utile?

Soluzione

Credo che questo potrebbe essere un problema trascurato nel quadro WPF.

Da quello che posso dire via Reflector, sembra che quando il dizionario risorse Application viene catastroficamente cambiato (un cambiamento che probabilmente avrà ampio effetti come l'aggiunta, rimozione o sostituzione di una pelle), v'è il codice che loop su tutto del Windows nell'applicazione e li costringe a rivalutare la loro DynamicResources. Tuttavia, altri elementi che considererei di livello superiore in WPF come ElementHosts non ricevono lo stesso trattamento. Questo porta al comportamento che sto vivendo.

La mia soluzione a questo problema è quello di passare manualmente attraverso tutti i miei ElementHosts individualmente e aggiungere, rimuovere o sostituire il file ResourceDictionary pelle. Non è perfetto, ma ottiene il lavoro fatto.

Altri suggerimenti

Un'altra soluzione potrebbe essere quella di creare una finestra fittizio e specificare il contenuto del ElementHost come contenuto. Se si guarda in dell'applicazione e controllare come gestisce i cambiamenti di resourcedictionaries, si vede che lo comunica solo Windows ..

L'unica cosa che si dovrebbe ricordare è quello di non visualizzare la finestra (-> eccezione), e per chiuderla lo smaltimento del ElementHost, per cui l'applicazione può spegnere correttamente

.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top