我正在尝试在我的UWP 10应用中创建一个设置,以便用户可以在运行时更改应用主题。我发现了一篇有趣的文章http://www.guruumeditation.net/en/changing-app-theme-on-the-fly-with-requestedtheme/,其中有一个名为 ThemeAwareFrame 的公共类:
public class ThemeAwareFrame : Frame
{
private static readonly ThemeProxyClass _themeProxyClass = new ThemeProxyClass();
public static readonly DependencyProperty AppThemeProperty = DependencyProperty.Register(
"AppTheme", typeof (ElementTheme), typeof (ThemeAwareFrame),
new PropertyMetadata(default(ElementTheme), (d,e) => _themeProxyClass.Theme = (ElementTheme)e.NewValue));
public ElementTheme AppTheme
{
get { return (ElementTheme) GetValue(AppThemeProperty); }
set { SetValue(AppThemeProperty, value); }
}
public ThemeAwareFrame()
{
var themeBinding = new Binding { Source = _themeProxyClass, Path = new PropertyPath("Theme") };
SetBinding(RequestedThemeProperty, themeBinding);
}
// Proxy class to be used as singleton
sealed class ThemeProxyClass : INotifyPropertyChanged
{
private ElementTheme _theme;
public ElementTheme Theme
{
get { return _theme; }
set
{
_theme = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在 App.xaml.cs 文件中,它的引用如下:
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new ThemeAwareFrame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(Shell), e.Arguments);
}
Window.Current.Activate();
}
}
在不同的页面上,可以使用以下代码更改应用主题:
(Frame as ThemeAwareFrame).AppTheme = ElementTheme.Light;
或
(Frame as ThemeAwareFrame).AppTheme = ElementTheme.Dark;
如果使用名为Shell的页面上的事件处理代码,则代码可以正常工作。但是,在我的应用程序中,Shell充当带有SplitView菜单的导航页面,并将不同的页面(例如“设置”)加载到名为MyFrame的Frame中。如果我尝试将代码移动到“设置”页面,我会得到一个NullReferenceExeption,因为该页面现在位于MyFrame中。 有没有人有解决方案我怎么能让这个工作? (我是c#编程的新手;))
答案 0 :(得分:0)
NullReferenceExeption,因为该页面现在位于MyFrame中。
这是因为您在MyFrame
SplitView
中<Frame x:Name="MyFrame" />
定义了MyFrame
Frame
ThemeAwareFrame
元素而不是Frame as ThemeAwareFrame
元素,所以当你试图通过ThemeAwareFrame
获取它时,你得到了null,因为你没有Frame
个对象,但你只有Settings
个对象。
在MyFrame
页面上,如果要更改当前框架MyFrame
的主题颜色,则需要将SplitView
内的ThemeAwareFrame
定义为<local:ThemeAwareFrame x:Name="MyFrame" Margin="0,5,0,0" />
如下:
Window.Current.Content
如果您想更改rootFrame(DarkTheme_OnClick
)的主题颜色,则需要更改private void DarkTheme_OnClick(object sender, RoutedEventArgs e)
{
ThemeAwareFrame rootFrame = Window.Current.Content as ThemeAwareFrame;
rootFrame.AppTheme = ElementTheme.Dark;
}
代码,如下所示:
DiagnosticSeverity.Error