2015-10-26 11 views
5

Meine Fragen sind sehr spezifisch für ThemeResources in einer Windows 10 Store App. Leider sind einige Dinge, die in "klassischem" WPF verfügbar sind, anders oder nicht verfügbar.ThemeResource im Code festlegen oder ändern

Was ich für viele UI-Elemente zu erreichen versuchen: (. In XAML dieses {ThemeResource SystemAccentColor} als Wert sein würde)

  • der Benutzer erlauben, das Systems der Akzentfarbe verwenden
  • Lassen Sie den Benutzer verwenden, eine benutzerdefinierte/feste Farbe stattdessen. (Ich konnte die SystemAccentColor Schlüssel in der Resource außer Kraft setzen)
  • zulassen zwischen System Akzent und benutzerdefinierte Farbe zur Laufzeit wechseln (I gegen eine Farbe binden könnte stattdessen eine Ressource verwenden)

Aber ich habe keine gefunden gute Lösung, um all dies zu erreichen. Wenn ich mein eigenes Ressourcenwörterbuch mit der benutzerdefinierten Farbe habe, werde ich es nicht loswerden, wenn der Benutzer zurück zur Akzentfarbe des Systems wechseln möchte. Und die Verwendung einer Eigenschaft, die ich bin bindend, hat den Nachteil, dass ich nicht merke, wenn der Benutzer die Akzentfarbe in den Systemeinstellungen ändert, während die App läuft - mit der {ThemeResource} Markup tut es.

Irgendwelche Ideen wie man das richtig macht? Wenn es möglich wäre, die ThemeResource von Code zu setzen, könnte ich etwas Verhalten dafür schreiben, aber es scheint nicht verfügbar zu sein.

Antwort

3

In 10 Windows ist der Name "Accent Color" wird auf "SystemControlHighlightAccentBrush", und es ist ein ThemeResource

Beispiel es

<TextBlock Foreground="{ThemeResource SystemControlHighlightAccentBrush}" 
        Text="This is a sample text" /> 

Um es außer Kraft verwenden, ändern Sie einfach Wert davon in App .xaml

<Application.Resources> 
    <SolidColorBrush x:Key="SystemControlHighlightAccentBrush" Color="Orange" /> 
</Application.Resources> 

zu wechseln, es ist ein wenig schwieriger Zuerst müssen Sie für jedes Thema in App.xam alle um die Farbe einzustellen l

<Application.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.ThemeDictionaries> 
      <ResourceDictionary x:Key="Default"> 
       <SolidColorBrush x:Key="SystemControlHighlightAccentBrush" Color="Orange" /> 
      </ResourceDictionary> 
      <ResourceDictionary x:Key="Dark"> 
       <SolidColorBrush x:Key="SystemControlHighlightAccentBrush" Color="Green" /> 
      </ResourceDictionary> 
      <ResourceDictionary x:Key="Light"> 
       <SolidColorBrush x:Key="SystemControlHighlightAccentBrush" Color="Blue" /> 
      </ResourceDictionary> 
     </ResourceDictionary.ThemeDictionaries> 
    </ResourceDictionary> 
</Application.Resources> 

Dann in der Seite oder in Code-behind, setzen Sie das entsprechende Thema

<TextBlock x:Name="TestTextBlock" 
       Foreground="{ThemeResource SystemControlHighlightAccentBrush}" 
       RequestedTheme="Dark" 
       Text="This is a sample text" /> 

oder in C#

TestTextBlock.RequestedTheme = ElementTheme.Dark; 
1

Einmal habe ich auch das gleiche Problem konfrontiert haben und Ich habe auch keinen Weg gefunden, programmatisch zu ändern ThemeResource, so dass es zusammen mit dem Thema des Telefons ändern wird. Nichtsdestotrotz gibt es einen Weg, um das zu erreichen, was Sie wollen, aber es ist umständlich und erfordert viel Arbeit, wenn Sie dies für viele Steuerelemente implementieren möchten.

Die Grundidee ist VisualStates verwenden von/bis ThemeResource zu ändern - die Zustände in XAML definiert sind, so dass diese mit ThemeResources arbeiten. Dann können Sie im Code die Änderung zurück zum Phone-Theme-Wert aufrufen. Hier unten ist der Beispiel-Button, der zur Farbe des Themas/Benutzers wechselt.

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
    <Button Name="ColorBtn" Content="Change users color to green rom red"/> 
    <local:ExtendedButton x:Name="UserBtn" Content="Change to user's theme" UserBackground="Red"> 
     <local:ExtendedButton.Style> 
      <Style TargetType="local:ExtendedButton"> 
       <!--default style's setters--> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="local:ExtendedButton"> 
          <Grid x:Name="RootGrid" Background="{TemplateBinding Background}"> 
           <VisualStateManager.VisualStateGroups> 
            <VisualStateGroup> 
             <VisualState x:Name="ThemeColor"> 
              <Storyboard> 
               <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid"> 
                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemColorControlAccentColor}"/> 
               </ObjectAnimationUsingKeyFrames> 
              </Storyboard> 
             </VisualState> 
             <VisualState x:Name="UserColor"/> 
            </VisualStateGroup> 
            <!--rest of default visual states--> 
           </VisualStateManager.VisualStateGroups> 
           <ContentPresenter x:Name="ContentPresenter" AutomationProperties.AccessibilityView="Raw" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="{TemplateBinding Content}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> 
          </Grid> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </local:ExtendedButton.Style> 
    </local:ExtendedButton> 
</StackPanel> 

und Code hinter:

public class ExtendedButton : Button 
{ 
    public SolidColorBrush UserBackground 
    { 
     get { return (SolidColorBrush)GetValue(UserBackgroundProperty); } 
     set { SetValue(UserBackgroundProperty, value); } 
    } 

    public static readonly DependencyProperty UserBackgroundProperty = 
     DependencyProperty.Register("UserBackground", typeof(SolidColorBrush), typeof(ExtendedButton), 
      new PropertyMetadata(new SolidColorBrush(Colors.Red), (s, e) => 
      { if ((s as ExtendedButton).IsUserTheme) (s as ExtendedButton).Background = e.NewValue as SolidColorBrush; })); 

    // we need some property to indicate if to use user's theme or phone's 
    public bool IsUserTheme 
    { 
     get { return (bool)GetValue(IsUserThemeProperty); } 
     set { SetValue(IsUserThemeProperty, value); } 
    } 

    public static readonly DependencyProperty IsUserThemeProperty = 
     DependencyProperty.Register("IsUserTheme", typeof(bool), typeof(ExtendedButton), new PropertyMetadata(false, (s, e) => 
     { 
      if ((bool)e.NewValue) 
      { 
       VisualStateManager.GoToState((s as ExtendedButton), "UserColor", false); 
       (s as ExtendedButton).Background = (s as ExtendedButton).UserBackground;     
      } 
      else VisualStateManager.GoToState((s as ExtendedButton), "ThemeColor", false); 
     })); 
} 

public sealed partial class MainPage : Page 
{ 
    public MainPage() 
    { 
     this.InitializeComponent(); 
     Random random = new Random(); 
     UserBtn.Click += (s, e) => UserBtn.IsUserTheme = !UserBtn.IsUserTheme; ; 
     ColorBtn.Click += (s, e) => UserBtn.UserBackground = new SolidColorBrush(Color.FromArgb(0xFF, (byte)random.Next(255), (byte)random.Next(255), (byte)random.Next(255))); 
    } 
} 

Es ist ein langer Weg, über nur eine Farbe zu ändern, sollte aber funktionieren und Ihnen vielleicht eine Idee geben. Diese sind auch DependencyProperties, so dass Sie Bindung bei Bedarf verwenden können.

+0

Vielleicht habe ich eine Lösung dafür gefunden. Schauen Sie sich meine Antwort an :) –

1

Es gibt einen Weg, wie man ThemeResource im Code einstellen ... Ich habe es nur auf W10 Creators Update getestet, so dass es möglicherweise nicht auf älteren Versionen funktioniert, aber Sie können Ihre eigene Ressource erstellen, die das Original ThemeResource referenziert Sie verwenden möchten, und dann diese Ressource nutzen:

XAML:

<SolidColorBrush x:Key="MyBorderBrush" Color="{ThemeResource SystemAccentColor}"/> 

C#:

element.BorderBrush = (SolidColorBrush)Resources["MyBorderBrush"]; 

Die Rahmenfarbe element entspricht der in den Windows-Einstellungen ausgewählten Accent Color und wird auch dann geändert, wenn Ihre App ausgeführt wird und der Benutzer sie ändert.

+0

Sieht so aus, als ob sich bei neueren Builds etwas geändert hat :) Schön, es scheint, als müsste ich etwas von meinem Code umschreiben. Danke für die Information. – Romasz