with the source resource present example attribute already xaml resources themes windows-10 uwp

xaml - present - Establecer o modificar ThemeResource en código



uwp resourcedictionary (3)

Mis preguntas son muy específicas de ThemeResources en una aplicación de Windows 10 Store. Desafortunadamente, varias cosas disponibles en WPF "clásico" son diferentes o no están disponibles aquí.

Lo que intento lograr para muchos elementos de la interfaz de usuario:

  • Permita que el usuario use el color de acento del sistema (en XAML esto sería {ThemeResource SystemAccentColor} como valor).
  • Permita que el usuario use un color personalizado / fijo en su lugar. (Podría anular la clave SystemAccentColor en el SystemAccentColor )
  • Permitir cambiar entre el acento del sistema y el color personalizado en el tiempo de ejecución (podría vincularme con un color en lugar de utilizar un recurso)

Pero no he encontrado una buena solución para lograr todo esto. Si tengo mi propio diccionario de recursos con el color personalizado, no me desharé de él cuando el usuario quiera volver al color de acento del sistema. Y usar una propiedad a la que me aferro tiene el inconveniente de que no me doy cuenta si el usuario cambia el color de acento en la configuración del sistema mientras la aplicación se está ejecutando, usando el marcado {ThemeResource} .

¿Alguna idea de cómo hacer esto correctamente? Si fuera posible configurar ThemeResource desde el código, podría escribir algún comportamiento para esto, pero parece que no está disponible.


En Windows 10, el nombre "Color de acento" se cambia a "SystemControlHighlightAccentBrush", y es un ThemeResource

Ejemplo usándolo

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

Para anularlo, simplemente cambie el valor de este en App.xaml

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

Para cambiar, es un poco más difícil. Primero, debe establecer todos los colores para cada tema en App.xaml

<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>

Luego, en la página o en el código detrás, configura el tema correspondiente

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

o en C #

TestTextBlock.RequestedTheme = ElementTheme.Dark;


Hay una manera de cómo configurar un ThemeResource en código ... Lo probé solo en W10 Creators Update, por lo que es posible que no funcione en versiones anteriores, pero puede crear su propio recurso que haga referencia al ThemeResource original que desea usar y luego usa este recurso:

XAML:

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

DO#:

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

El color del borde del element será el mismo que el del Color de acento seleccionado en la Configuración de Windows y cambiará incluso cuando la aplicación se esté ejecutando y el usuario la cambie.


Una vez también he enfrentado el mismo problema y tampoco he encontrado una manera de cambiar programáticamente ThemeResource para que cambie junto con el tema del teléfono. Sin embargo, hay una manera de lograr lo que desea, pero es engorroso y puede requerir mucho trabajo cuando desea implementar esto para muchos controles.

La idea básica es usar VisualStates para cambiar de / a ThemeResource : los estados se definen en xaml, por lo que esto funcionará con ThemeResources . Luego, en el código puede invocar el cambio de nuevo al valor del tema del teléfono. A continuación, el botón de muestra cambia al color del tema / usuario.

<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>

y código detrás:

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

Está muy por encima de simplemente cambiar un color, pero debería funcionar y tal vez te dé una idea. Esas también son DependencyProperties por lo que puede usar el enlace si es necesario.