2016-09-22 134 views
0

我想在我的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充當具有SplitView菜單的導航頁面,並將不同的頁面(例如設置)加載到名爲MyFrame的Frame中。如果我嘗試將代碼移動到設置頁面,我得到一個NullReferenceExeption,因爲該頁面現在位於MyFrame中。 有沒有人有解決方案,我怎麼能得到這個工作? (我是c#編程的新手);)

回答

0

NullReferenceExeption因爲頁面現在位於MyFrame中。

這是因爲你在SplitView定義的MyFrame通過<Frame x:Name="MyFrame" />MyFrame將是一個Frame元素不是ThemeAwareFrame元素,所以當你試圖通過Frame as ThemeAwareFrame得到它,因爲你沒有一個ThemeAwareFrame你得了空對象,但您只有一個Frame對象。

Settings頁面,如果你想改變當前幀MyFrame的主題顏色,你需要定義MyFrame這是內部SplitViewThemeAwareFrame喜歡如下:

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

如果你想改變的主題(Window.Current.Content),您需要更改DarkTheme_OnClick代碼,如下所示:

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