在ElementHost的托管时,动态应用程序级别的资源不是动态
-
05-09-2019 - |
题
我在一个WinForms容器托管WPF用户控件。现在,我希望能够主题/皮肤的用户控件。要做到这一点,我已经得到了确定的几个资源字典“皮肤”。当我的应用程序启动时创建一个“新System.Windows.Application()”,使Application.Current存在。要更改主题的老旧角质去掉是一个新的皮肤合并到在运行应用程序级别的资源字典。然而,这并不在用户控件更改任何dyanamically引用的资源。我在一条直线WPF应用程序尝试这样做,它的工作就好了。我缺少的东西,或者是根本不可能做到这一点?顺便说一句,如果我补充皮肤到应用程序资源的用户控件初始化之前会工作,但之后我改变不了皮肤。
要在最基本的方式回购这样:
创建一个新的WinForms应用程序。添加一个WPF用户控件的应用程序。这是很简单的:
<UserControl ...>
<Grid>
<Button
Background="{DynamicResource ButtonBG}"/>
</Grid>
</UserControl>
创建两个ResourceDictionaries,White.xaml和Black.xaml(或其他)具有与各颜色的键ButtonBG一个的SolidColorBrush。在Form1.cs,添加两个按钮和一个ElementHost的。在ElementHost的的孩子设置为我们刚刚创建的用户控件的一个实例。线向上的按钮,以便交换皮肤事件:
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存在,并且设置初始皮肤:
[STAThread]
static void Main()
{
new System.Windows.Application();
Application.Current.Resources.MergedDictionaries[0] =
(ResourceDictionary)Application.LoadComponent(
new Uri(@"\WpfThemes;component\White.xaml", UriKind.Relative)));
...
}
现在,当白色的按钮被点击我希望在用户控件按钮打开白色,点击黑色按钮时,我希望按钮变为黑色。然而,这并不发生。
有谁知道为什么吗?是否有一个解决方案?
编辑:理念:也许,如果有一种方法来强制DynamicResources的重新评估当主题的变化,将工作
谢谢, 多尘
解决方案
我觉得这可能是WPF框架的忽视的问题。
从我可以通过反射出来,看来当Application
资源字典是灾难性的改变(改变,将可能具有广泛的,如添加,删除或替换皮肤的效果),有一个遍历所有代码在应用程序和部队Windows
的他们重新评估他们DynamicResources
。但是,其他的元素,我会考虑的顶级的WPF中像ElementHost
s没有得到同样的待遇。这导致了我遇到的行为。
我的解决方法,此问题已通过所有我ElementHost
s的手动去独立,并添加,删除或更换皮肤ResourceDictionary
文件。它并不完美,但它能够完成任务。
其他提示
另一个解决方法是创建一个虚拟的窗口,并指定作为ElementHost的内容的内容。 如果您仔细查看应用程序,并检查它如何处理resourcedictionaries的变化,你会发现它只是通知窗口..
您应该提醒的唯一的东西是永远不要显示窗口( - >除外),以及处置的ElementHost的时候将其关闭,这样应用程序可以正常关机
。