Я динамически загружаю словари ресурсов приложения (загружено 2 из 3 одновременно):
- словарь базовых ресурсов, всегда
- файл темы Light.xaml
- файл темы Dark.xaml
Если я обычно изменяю значение свойства MergedDictionaries
, когда главное окно уже Loaded
, я получаю исключение (стек вызовов здесь ):
System.InvalidOperationException: 'Невозможно вызвать StartAt во время создания контента.'
Если я изменю MergedDictionaries
Значение свойства, использующее Dispatcher.BeginInvoke
, когда я использую ресурс в коде от (1), через исключение он говорит, что оно еще не загружено (например, использование ресурса через StaticResource
, который не существует).
Я не хочу использовать файл App.xaml, потому что для приложения с одним экземпляром я использую класс, который наследуется от Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase
и вызывает код в моем файле App.cs.
Я могу вызвать метод LoadTheme в нескольких местах кода приложения, и я хочусделать его стабильным.
App.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, Win10 Pro.
Спасибо.