参照框架

本文关键字:框架 | 更新日期: 2023-09-27 18:08:14

我试图在我的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 . xml .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的框架中。如果我尝试将代码移动到设置页面,我会得到一个nullreferenceexception,因为页面现在位于MyFrame中。谁有解决方案,我怎么才能让它工作?(我是c#编程新手;))

参照框架

nullreferenceexception,因为页面现在位于MyFrame中。

这是因为您通过<Frame x:Name="MyFrame" />SplitView中定义了MyFrame,其中MyFrame将是Frame元素而不是ThemeAwareFrame元素,因此当您尝试通过Frame as ThemeAwareFrame获得它时,您得到null,因为您没有ThemeAwareFrame对象,但您只有Frame对象。

Settings页面上,如果你想改变当前框架MyFrame的主题颜色,你需要将SplitView内部的MyFrame定义为ThemeAwareFrame,如下所示:

<local:ThemeAwareFrame x:Name="MyFrame" Margin="0,5,0,0"   />   

如果你想改变rootFrame(Window.Current.Content)的主题颜色,你需要像下面这样改变DarkTheme_OnClick代码:

private void DarkTheme_OnClick(object sender, RoutedEventArgs e)
{
    ThemeAwareFrame rootFrame = Window.Current.Content as ThemeAwareFrame;
    rootFrame.AppTheme = ElementTheme.Dark;
 }