我会认为这是设计。当我们为应用程序创建多个窗口时,每个窗口的行为都是独立的。每个窗口都在自己的线程中运行。每个窗口中使用的Application.Resources
也是独立的。
Application.Resources是ResourceDictionary对象和ResourceDictionary类从DependencyObject继承,所以Application.Resources
也是DependencyObject
实例。
所有DependencyObject实例必须是与当前Window为一个应用程序相关的UI线程上创建。这是由系统执行,并且也有这对于你的代码的两个重要含义:使用API从两个DependencyObject实例将始终在同一个线程,它总是在UI线程上运行
欲了解更多信息,请参阅的DependencyObject和DependencyObjectRemarks下穿。
所以每个Window有它自己的Application.Resources
。在次要视图中,您的ResourceDictionary
将重新评估Application.Resources
。该BackgroundBrush
不会在主视图设置的影响与下面的代码
(Application.Current.Resources["BackgroundBrush"] as SolidColorBrush).Color = Windows.UI.Colors.Black;
只更改与主视图的Window相关的Application.Current.Resources
实例。
如果您希望辅助视图使用与主视图相同的画笔,我认为您可以将此颜色存储在主视图中,然后在创建辅助视图时应用它。例如,我在App
类添加一个名为BackgroundBrushColor
静态字段,然后使用它像以下:
private void ThemeChanger_Click(object sender, RoutedEventArgs e)
{
App.BackgroundBrushColor = Windows.UI.Color.FromArgb(Convert.ToByte(random.Next(255)), Convert.ToByte(random.Next(255)), Convert.ToByte(random.Next(255)), Convert.ToByte(random.Next(255)));
(Application.Current.Resources["BackgroundBrush"] as SolidColorBrush).Color = App.BackgroundBrushColor;
}
private async Task CreateNewViewAsync()
{
CoreApplicationView newView = CoreApplication.CreateNewView();
int newViewId = 0;
await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() =>
{
(Application.Current.Resources["BackgroundBrush"] as SolidColorBrush).Color = App.BackgroundBrushColor;
Frame frame = new Frame();
frame.Navigate(typeof(SecondaryPage), null);
Window.Current.Content = frame;
// You have to activate the window in order to show it later.
Window.Current.Activate();
newViewId = ApplicationView.GetForCurrentView().Id;
});
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId);
}
我已经改变了代码来修改每个视图中的资源。如果您在更改值之前在SecondaryPage.xaml.cs中的ThemeChanged方法中设置断点,则可以看到资源的值已更改为已更新的值。但它并没有反映在这个角度。
这里的问题是,因为你的ThemeChanged
事件在主视图中引发的,因此它在主视图中的线程中运行,因此你在SecondaryPage.xaml.cs使用ThemeManager_ThemeChanged
方法也将在主视图的运行线。这导致Application.Current.Resources
在ThemeManager_ThemeChanged
方法中仍然获得与主视图关联的ResourceDictionary
实例。这就是为什么资源的价值已经改变到更新的价值,并不会反映在视图中。为了清楚地看到这一点,您可以在调试时利用Threads Window。
为了解决这个问题,你可以使用this.Dispatcher.RunAsync
方法在正确的线程类似下面的运行代码:
private async void ThemeManager_ThemeChanged(Utils.ThemeManager theme)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() =>
{
((SolidColorBrush)Application.Current.Resources["BackgroundBrush"]).Color = theme.HighAccentColorBrush.Color;
});
}
但是,有了这个,你仍然会得到这样的错误:“应用程序调用一个接口被编组为一个不同的线程“这是因为SolidColorBrush类也继承DependencyObject。为了解决这个问题,我建议改变从SolidColorBrushHighAccentColorBrush
类型Color,然后用它喜欢:
private async void ThemeManager_ThemeChanged(Utils.ThemeManager theme)
{
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,() =>
{
((SolidColorBrush)Application.Current.Resources["BackgroundBrush"]).Color = theme.HighAccentColorBrush;
});
}
我使用风格而不是主题!通过使用风格,我们可以更新外观和感觉与重新启动应用程序。 – Nilay
https://github.com/Kumara-Krishnan/ThemePOC – Razor
@ JayZuo-MSFT即使在更改资源值后,辅助视图仍具有最初在资源字典中指定的值。 – Razor