0

我动态加载应用程序资源字典(一次加载 3 个中的 2 个):

  1. 一个基本资源字典,总是
  2. Light.xaml 主题文件
  3. Dark.xaml 主题文件

MergedDictionaries如果我通常在主窗口已经存在时更改属性的值Loaded,我会得到一个异常(在此处调用堆栈):

System.InvalidOperationException: “内容生成正在进行时无法调用 StartAt。”

如果我使用 更改MergedDictionaries属性的值Dispatcher.BeginInvoke,当我在 (1) 的代码隐藏中使用资源时,它会通过一个异常表示它尚未加载(例如使用StaticResource不存在的资源)。

我不想使用 App.xaml 文件,因为对于单实例应用程序,我使用了一个类,该类继承自Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase并调用我的 App.cs 文件中的代码。

我可能会在应用程序代码的几个地方调用 LoadTheme 方法,我想让它稳定。

应用程序.cs

(无 XAML)

public class App : System.Windows.Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        LoadTheme(AppTheme.Light);
        var w = new MainWindow();
        ShutdownMode = ShutdownMode.OnMainWindowClose;
        MainWindow = w;
        w.Show();
    }
    internal ResourceDictionary MLight = null,
        MDark = null,
        MMain = null;
    internal ResourceDictionary GetLightThemeDictionary()
    {
        if (MLight == null)
        {
            MLight = new ResourceDictionary() { Source = new Uri("Themes/Light.xaml", UriKind.Relative) };
        }
        return MLight;
    }
    internal ResourceDictionary GetDarkThemeDictionary()
    {
        if (MDark == null)
        {
            MDark = new ResourceDictionary() { Source = new Uri("Themes/Dark.xaml", UriKind.Relative) };
        }
        return MDark;
    }
    internal ResourceDictionary GetMainDictionary()
    {
        if (MMain == null)
        {
            MMain = new ResourceDictionary() { Source = new Uri("AppResources.xaml", UriKind.Relative) };
        }
        return MMain;
    }
    internal void LoadTheme(AppTheme t)
    {
        //Dispatcher.BeginInvoke(new Action(() =>
        //{
            if (Resources.MergedDictionaries.Count == 2)
            {
                switch (t)
                {
                    case AppTheme.Dark:
                        Resources.MergedDictionaries[1] = GetDarkThemeDictionary();
                        break;
                    default:
                        Resources.MergedDictionaries[1] = GetLightThemeDictionary();
                        break;
                }
            }
            else if (Resources.MergedDictionaries.Count == 1)
            {
                switch (t)
                {
                    case AppTheme.Dark:
                        Resources.MergedDictionaries.Add(GetDarkThemeDictionary());
                        break;
                    default:
                        Resources.MergedDictionaries.Add(GetLightThemeDictionary());
                        break;
                }
            }
            else
            {
                Resources.MergedDictionaries.Clear();
                Resources.MergedDictionaries.Add(GetMainDictionary());
                LoadTheme(t);
            }
        //}), System.Windows.Threading.DispatcherPriority.Normal); // how to process this after the ItemsControl has generated its elements?
    }
}

我试图制作一个测试示例,但失败了 - 我创建了一个可以工作的程序,因为我在ItemsControl.ItemsSource每次应用模板时都设置了。在我的实际项目中,我ItemsSource通过数据绑定设置,有时是手动设置,但我不确定这是我实际项目中遗漏的内容。

我使用 .NET Framework 4.7.2、VS 2019、Win 10 Pro。

谢谢你。

4

1 回答 1

0

OnStartup方法现在看起来像这样(我只是在构建之前加载了基本字典和主题之一MainWindow):

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    Resources.MergedDictionaries.Clear();
    Resources.MergedDictionaries.Add(GetMainDictionary());
    Resources.MergedDictionaries.Add(GetLightThemeDictionary());

    LoadTheme(AppTheme.Light);

    var w = new MainWindow();

    ShutdownMode = ShutdownMode.OnMainWindowClose;
    MainWindow = w;

    w.Show();
}

我取消了 2 条评论(使用 Dispatcher)的注释:

internal void LoadTheme(AppTheme t)
{
    Dispatcher.BeginInvoke(new Action(() =>
    {
        [...]
    }), System.Windows.Threading.DispatcherPriority.Normal);
}
于 2019-09-19T10:05:54.287 回答