如何在 ItemsControl 生成其容器之前或之后更改加载的主题资源字典,但不是在这段时间内?



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

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

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

System.InvalidOperationException:">在内容生成过程中无法调用 StartAt。

如果我使用Dispatcher.BeginInvoke更改MergedDictionaries属性的值,当我在 (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。

谢谢。

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 条评论(使用调度程序(:

internal void LoadTheme(AppTheme t)
{
Dispatcher.BeginInvoke(new Action(() =>
{
[...]
}), System.Windows.Threading.DispatcherPriority.Normal);
}

最新更新