托管在ElementHost中时,动态应用程序级资源不是动态的 [英] Dynamic Application-level resources are not dynamic when hosted in ElementHost

查看:110
本文介绍了托管在ElementHost中时,动态应用程序级资源不是动态的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在WinForms容器中托管WPF UserControl.现在,我希望能够为UserControl设置主题/外观.为此,我有几个定义皮肤"的资源词典.当我的应用程序启动时,我创建一个新System.Windows.Application()",以便存在Application.Current.要更改主题,请在运行时删除旧皮肤并将新皮肤合并到应用程序级资源字典中.但是,这不会更改UserControl中任何动态引用的资源.我在直接的WPF应用程序中进行了尝试,效果很好.我是否缺少某些东西,还是根本不可能做到这一点?顺便说一句,如果在初始化UserControl之前将皮肤添加到应用程序资源中,它将可以使用,但是之后我将无法更改皮肤.

I'm hosting a WPF UserControl in a WinForms container. Now, I want to be able to theme/skin the UserControl. To do this, I've got several resource dictionaries that define the "skins." When my app starts up I create a "new System.Windows.Application()" so that Application.Current exists. To change the theme the old skin is removed and a new skin is merged into the Application level resource dictionary at runtime. However, this does not change any of the dyanamically referenced resources in the UserControl. I tried this in a straight WPF application and it worked just fine. Am I missing something, or is it not possible to do this at all? By the way, if I add a skin into the application resources before the UserControl is initialized it will work but I cannot change the skin after that.

以最基本的方式回购此商品:

To repo this in the most basic way:

创建一个新的WinForms应用程序.将WPF UserControl添加到应用程序.这很简单:

Create a new WinForms application. Add a WPF UserControl to the app. This is simple enough:

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

创建两个ResourceDictionaries,White.xaml和Black.xaml(或其他),它们都有一个SolidColorBrush,其按键ButtonBG具有各自的颜色.在Form1.cs中,添加两个Button和一个ElementHost.将ElementHost的子级设置为我们刚刚创建的UserControl的实例.将按钮连接到交换皮肤的事件:

Create two ResourceDictionaries, White.xaml and Black.xaml (or whatever) that have a SolidColorBrush with the key ButtonBG with respective color. In Form1.cs, add two Buttons and an ElementHost. Set the child of the ElementHost to an instance of the UserControl we just created. Wire up the buttons to events that swap the skin:

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

在Program.cs中,确保存在Application.Current并设置初始外观:

In Program.cs, ensure that Application.Current exists and set the initial skin:

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

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

   ...
}

现在,当单击白色"按钮时,我希望UserControl中的按钮变为白色,而当单击黑色"按钮时,我希望该按钮变为黑色.但是,这不会发生.

Now, when the White button is clicked I would expect the button in the UserControl to turn white and when the Black button is clicked I would expect the button to turn black. This does not happen, however.

有人知道为什么吗?有解决办法吗?

Does anyone know why? Is there a solution?

想法:也许,如果有一种方法可以在主题更改时强制对DynamicResources进行重新评估,那将是可行的.

Idea: Perhaps, if there's a way to force re-evaluation of DynamicResources when the theme changes, that would work.

谢谢, 尘土飞扬

推荐答案

我认为这可能是WPF框架中一个被忽视的问题.

I think this may be an overlooked issue in the WPF framework.

据我通过Reflector的了解,看来Application资源字典发生了灾难性的变化(这种变化可能会产生广泛的影响,例如添加,移除或替换皮肤),其中有一些代码会循环覆盖应用程序中的所有Windows,并迫使他们重新评估其DynamicResources.但是,我认为在WPF中顶级的其他元素(例如ElementHost)不会得到相同的待遇.这导致了我正在经历的行为.

From what I can tell via Reflector, it appears that when the Application resource dictionary is catastrophically changed (a change that will likely have wide ranging effects like adding, removing, or replacing a skin), there is code that loops over all of the Windows in the application and forces them to re-evaluate their DynamicResources. However, other elements that I would consider top-level in WPF like ElementHosts do not get the same treatment. This leads to the behavior that I'm experiencing.

我对此问题的解决方法是手动逐个遍历所有ElementHost并添加,删除或替换皮肤ResourceDictionary文件.它不是完美的,但是可以完成工作.

My workaround to this issue is to manually go through all of my ElementHosts individually and add, remove, or replace the skin ResourceDictionary file. It's not perfect, but it gets the job done.

这篇关于托管在ElementHost中时,动态应用程序级资源不是动态的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆