2016-06-19 11 views
0

Ich habe eine Lücke, die ein Bild analysiert, extrahiert zwei dominierende Farben und ersetzt "SystemControlForegroundAccentBrush" und "SystemControlHighlightAccentBrush", die ich in App.xaml überschreiben. Es funktioniert gut, außer dass es ein wenig Zeit braucht, um das Bild zu analysieren, also ändert es die Farben, sobald alle Steuerelemente auf meiner Seite bereits geladen sind. Dadurch behalten sie die alte Akzentfarbe. Wie kann ich sie dazu bringen, dynamisch an diese ThemeRessource zu binden?Aktualisieren ThemeResources von C#?

Hier ist meine app.xaml:

<Application.Resources> 
    <ResourceDictionary x:Name="resdic"> 
     <ResourceDictionary.ThemeDictionaries> 
      <ResourceDictionary x:Key="Dark"> 
       <SolidColorBrush x:Key="SystemControlForegroundAccentBrush"/> 
       <SolidColorBrush x:Key="SystemControlHighlightAccentBrush"/> 
      </ResourceDictionary> 
     </ResourceDictionary.ThemeDictionaries> 
    </ResourceDictionary> 
</Application.Resources> 

Dies ist der (sehr vereinfacht) Teil der ColorExtractor.cs Klasse, die die Farben ändert:

public async static void Analyse() 
{ 
    Application.Current.Resources["SystemControlForegroundAccentBrush"] = new SolidColorBrush(color); 
    Application.Current.Resources["SystemControlHighlightAccentBrush"] = new SolidColorBrush(color2); 
} 

Und ich habe eine Reihe bekommt von Kontrollen in Page.xaml, die ihren Vordergrund als solche festgelegt haben:

<TextBlock Foreground="{ThemeResource SystemControlForegroundAccentBrush]"/> 

ich nenne ColorExtractor.Analyse() in meiner Page.xaml.cs (beim OnNavigatedTo-Ereignis). Ich kann immer ein Ereignis erstellen, das ausgelöst wird, sobald die Farben eingestellt sind, aber ich muss einen Weg finden, um die Farben aller Steuerelemente auf meiner Seite zu aktualisieren, wenn das erledigt ist.

+0

Können Sie mir bitte einen Code schreiben, der mir hilft zu verstehen, was Sie tun? Sie können versuchen, eine Eigenschaft an 'ThemeResource 'zu binden und' INotifyPropertyChanged 'für diese Eigenschaft zu implementieren. –

+0

Ich habe mein OP mit etwas Code aktualisiert. – user2950509

Antwort

0

Am Ende habe ich beschlossen, ein Ereignis in ColorExtractor zu erstellen.cs:

public static event EventHandler Analysed; 
public async static void Analyse(BitmapImage poster) 
{ 
    //Analyse colors 
    Analysed(null, null); 
} 

Und dann, auf meinem MainPage.xaml.cs:

ColorExtractor.Analyse(bmp); 
ColorExtractor.Analysed += (sender, EventArgs) => 
{ 
    //Set Page foreground color, as a lot of controls are dynamically binded to their parent's foreground brush. 
    //If a control isn't automatically binded, all I have to do is say: Foreground="{Binding Foreground, ElementName=page}" 
    page.Foreground = Application.Current.Resources["SystemControlForegroundAccentBrush"] as SolidColorBrush; 
    page.BorderBrush = Application.Current.Resources["SystemControlHighlightAccentBrush"] as SolidColorBrush; 
    //Reload any custom user control that sets it's children's color when it's loaded. 
    backdrop.UserControl_Loaded(null, null); 
}; 

Also ich bin eigentlich nicht direkt meine Kontrollen an den ForegroundAccentBrush verbindlich, aber das funktioniert, ohne neu zu navigierenden auf die Seite.

0

Sie können sehen, wie sich Template Theming-Änderungen ändert, aber in ihrem Fall definieren sie im Voraus zwei verschiedene Themen in Ressourcen-Wörterbüchern. Sie können ihren Code in der repo on Github, finden aber hier einige der Code verwendet:

(Window.Current.Content as FrameworkElement).RequestedTheme = value.ToElementTheme(); 
Views.Shell.SetRequestedTheme(value, UseBackgroundChecked); 

Von here

public static void SetRequestedTheme(ApplicationTheme theme, bool UseBackgroundChecked) 
    { 

     WindowWrapper.Current().Dispatcher.Dispatch(() => 
     { 
      (Window.Current.Content as FrameworkElement).RequestedTheme = theme.ToElementTheme(); 

      ParseStyleforThemes(theme); 

      HamburgerMenu.NavButtonCheckedForeground = NavButtonCheckedForegroundBrush; 

      HamburgerMenu.NavButtonCheckedBackground = (UseBackgroundChecked) ? 
       NavButtonCheckedBackgroundBrush : NavButtonBackgroundBrush; 

      HamburgerMenu.NavButtonCheckedIndicatorBrush = (UseBackgroundChecked) ? 
       Colors.Transparent.ToSolidColorBrush() : NavButtonCheckedIndicatorBrush; 

      HamburgerMenu.SecondarySeparator = SecondarySeparatorBrush; 

      List<HamburgerButtonInfo> NavButtons = HamburgerMenu.PrimaryButtons.ToList(); 
      NavButtons.InsertRange(NavButtons.Count, HamburgerMenu.SecondaryButtons.ToList()); 

      List<HamburgerMenu.InfoElement> LoadedNavButtons = new List<HamburgerMenu.InfoElement>(); 

      foreach (var hbi in NavButtons) 
      { 
       StackPanel sp = hbi.Content as StackPanel; 
       if (hbi.ButtonType == HamburgerButtonInfo.ButtonTypes.Literal) continue; 
       ToggleButton tBtn = sp.Parent as ToggleButton; 
       Button btn = sp.Parent as Button; 

       if (tBtn != null) 
       { 
        var button = new HamburgerMenu.InfoElement(tBtn); 
        LoadedNavButtons.Add(button); 
       } 
       else if (btn != null) 
       { 
        var button = new HamburgerMenu.InfoElement(btn); 
        LoadedNavButtons.Add(button); 
        continue; 
       } 
       else 
       { 
        continue; 
       } 

       Rectangle indicator = tBtn.FirstChild<Rectangle>(); 
       indicator.Visibility = ((!hbi.IsChecked ?? false)) ? Visibility.Collapsed : Visibility.Visible; 

       if (!hbi.IsChecked ?? false) continue; 

       ContentPresenter cp = tBtn.FirstAncestor<ContentPresenter>(); 
       cp.Background = NavButtonCheckedBackgroundBrush; 
       cp.Foreground = NavButtonCheckedForegroundBrush; 
      } 

      LoadedNavButtons.ForEach(x => x.RefreshVisualState()); 

     }); 
    } 

Von here

0

ich eine Lücke haben, die Analysen ein Bild, extrahiert zwei dominierende Farben und ersetzt "SystemControlForegroundAccentBrush" und "SystemControlHighlightAccentBrush", die ich in App.xaml überschreibe.

Zuerst habe ich glaube nicht, Ihren Code in app.xaml die ThemeResource außer Kraft setzen können, und Sie verwendet, um dieses Brush in der Seite wie folgt aus:

<TextBlock Foreground="{ThemeResource SystemControlForegroundAccentBrush}" Text="Hello World!" FontSize="50" /> 

Wenn Sie "F12" auf der SystemControlForegroundAccentBrush drücken Sie finden diese Ressource tatsächlich in der Datei "generic.xaml".

Nun angenommen, Ihre ColorExtractor.cs Klasse funktioniert gut und ColorExtractor.Analyse() kann die Farbe dieser beiden Pinsel überschreiben, und Sie haben viele Steuerelemente in der Seite verwendet diese beiden Ressourcen, Aktualisieren der Seite hier kann Ihr Problem lösen.

Aber ich denke, es ist besser, dass diese Operation nicht in OnNavagateTo Ereignis setzen oder Page.Loaded Ereignis gibt es keine Aktualisierungsmethode in UWP ist, verwenden wir die Navigation wieder auf diese Seite zu aktualisieren, so dass, wenn die Umsetzung dieses Betrieb in OnNavagateTo Ereignis oder Page.Loaded Ereignis Jedes Mal, wenn Sie auf diese Seite navigieren, werden die Ressourcen überschrieben und es wird wieder navigiert. Also habe ich diesen Vorgang in ein Button-Klick-Ereignis wie dieses eingefügt:

public bool Reload() 
{ 
    return Reload(null); 
} 

private bool Reload(object param) 
{ 
    Type type = this.Frame.CurrentSourcePageType; 
    if (this.Frame.BackStack.Any()) 
    { 
     type = this.Frame.BackStack.Last().SourcePageType; 
     param = this.Frame.BackStack.Last().Parameter; 
    } 
    try { return this.Frame.Navigate(type, param); } 
    finally 
    { 
     this.Frame.BackStack.Remove(this.Frame.BackStack.Last()); 
    } 
} 

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    ColorExtractor.Analyse(); 
    Reload(); 
} 
Verwandte Themen