2016-09-22 8 views
0

Ich versuche, eine Einstellung in meiner UWP 10 App zu erstellen, damit der Benutzer das App-Design zur Laufzeit ändern kann. Ich fand einen interessanten Artikel http://www.guruumeditation.net/en/changing-app-theme-on-the-fly-with-requestedtheme/ wo diese mit einer öffentlichen Klasse mit dem Namen getan wird ThemeAwareFrame:Mit Bezug auf Frames

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)); 
        } 
    } 
} 

In den App.xaml.cs Datei, um sie dann diese mögen verwiesen wird:

  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(); 
     } 
    } 

Auf den verschiedenen Seiten kann dann das App-Design unter Verwendung des folgenden Codes geändert werden:

(Frame as ThemeAwareFrame).AppTheme = ElementTheme.Light; 

oder

(Frame as ThemeAwareFrame).AppTheme = ElementTheme.Dark; 

Der Code funktioniert gut, wenn es mit einem Ereignisse auf der Seite mit dem Namen Shell behandelt wird. In meiner App fungiert Shell jedoch als Navigationsseite mit einem SplitView-Menü und lädt die verschiedenen Seiten, z. B. Einstellungen, in einen Frame namens MyFrame. Wenn ich versuche, den Code auf die Einstellungsseite zu verschieben, erhalte ich eine NullReferenceExeption, weil die Seite jetzt in MyFrame sitzt. Hat jemand eine Lösung, wie ich das zum Funktionieren bringen kann? (Ich bin neu in C# Programmierung;))

Antwort

0

NullReferenceExeption, weil die Seite jetzt in MyFrame sitzt.

Dies ist, weil Sie die MyFrame im SplitView von <Frame x:Name="MyFrame" /> die MyFrame definiert ein Frame Element kein ThemeAwareFrame Element sein wird, so dass, wenn Sie versuchen, es zu erhalten, indem Frame as ThemeAwareFrame du hast null, da Sie kein ThemeAwareFrame haben Objekt, aber Sie haben nur ein Frame Objekt.

Auf der Settings Seite, wenn Sie das Thema Farbe des aktuellen Rahmens MyFrame ändern möchten, müssen Sie MyFrame definieren, die innerhalb SplitView ist als ThemeAwareFrame wie folgt:

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

Wenn Sie das Thema ändern möchten Farbe von rootFrame (Window.Current.Content), müssen Sie den DarkTheme_OnClick Code wie folgt ändern:

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