代码之家  ›  专栏  ›  技术社区  ›  dustyburwell

当托管在elementhost中时,动态应用程序级资源不是动态的

  •  5
  • dustyburwell  · 技术社区  · 17 年前

    我正在WinForms容器中托管一个WPF用户控件。现在,我希望能够为用户控件设置主题/外观。为此,我有几个资源字典定义了“皮肤”。当我的应用程序启动时,我创建了一个“new system.windows.application()”,这样应用程序.current就存在了。要更改主题,将删除旧外观,并在运行时将新外观合并到应用程序级资源字典中。但是,这不会改变用户控件中任意动态引用的资源。我在一个直接的WPF应用程序中尝试了这个方法,它运行得很好。我是错过了什么,还是根本做不到?顺便说一句,如果在初始化用户控件之前向应用程序资源中添加一个外观,它将起作用,但在此之后我不能更改外观。

    以最基本的方式回购:

    创建新的WinForms应用程序。向应用程序添加WPF用户控件。这很简单:

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

    创建两个ResourceDictionary,分别是white.xaml和black.xaml(或其他),其中solidColorBrush具有相应颜色的键buttonbg。在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)));
    
       ...
    }
    

    现在,单击白色按钮时,我希望用户控件中的按钮变白,单击黑色按钮时,我希望按钮变黑。然而,这并没有发生。

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

    编辑: 想法:也许,如果有一种方法可以在主题改变时强制重新评估动态资源,那就行了。

    谢谢, 尘土飞扬的

    2 回复  |  直到 12 年前
        1
  •  6
  •   dustyburwell    17 年前

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

    从我通过反射镜可以看出,当 Application 资源字典发生了灾难性的变化(这种变化可能会产生广泛的影响,如添加、删除或替换皮肤),有代码在所有 Windows 在应用程序中,强制他们重新评估 DynamicResources . 但是,我会考虑的其他因素 顶层 在WPF中 ElementHost S不接受同样的治疗。这导致了我正在经历的行为。

    我解决这个问题的方法是手动完成 元素元素 单独添加、移除或更换皮肤 ResourceDictionary 文件。这并不完美,但能完成任务。

        2
  •  -1
  •   lola0011    12 年前

    另一个解决方法是创建一个虚拟窗口,并将elementhost的内容指定为内容。 如果您查看应用程序并检查它如何处理资源字典的更改,您会发现它只通知Windows。

    唯一需要提醒的是,不要显示窗口(->异常),并在处理elementhost时关闭它,这样应用程序才能正常关闭。