3
votes

I'm working with WP7, and i'd like to create a custom brush (as a local resource) that uses different colors for dark and light themes (for instace, red if the theme is black and blue if it's white).

How do i do it?

Thanks!

3

3 Answers

5
votes

The integrated/system brushes do not change their properties based on the theme, a different set of brushes is included based on the current theme. You can see the various versions of this in %programfiles%\Microsoft SDKs\Windows Phone\v7.1\Design

I wrote a custom ResourceDictionary that implements theme support in the exact same way: by loading the appropriate theme dictionary depending on the light/dark theme.

Here is a sample that uses it. It works in the Visual Studio designer as well as Blend, but doesn't support white theme preview in Blend because Blend loads resources in a way that cannot be reproduced.

<Application.Resources>
    <custom:ThemeResourceDictionary>
        <custom:ThemeResourceDictionary.LightResources>
            <ResourceDictionary Source="/ThemeManagement;component/Resources/Light.xaml" />
        </custom:ThemeResourceDictionary.LightResources>
        <custom:ThemeResourceDictionary.DarkResources>
            <ResourceDictionary Source="/ThemeManagement;component/Resources/Dark.xaml" />
        </custom:ThemeResourceDictionary.DarkResources>
    </custom:ThemeResourceDictionary>
</Application.Resources>

The above code loads in the resources from two different files, but they could just as easily be declared inline like any other ResourceDictionary.

The source for ThemeResourceDictionary is available on my original blog post, but it's also on a different Stack Overflow question in case my blog ever implodes.

2
votes

You will have to manage brushes you apply to your elements yourself from code. Currently, I have found this to be the only way of adjusting to a different PhoneBackgroundColor.

For example:

In xaml

<TextBlock Text="Some text" Foreground="{Binding VariableTextColor}"/>

In code

var backgroundColor = (System.Windows.Media.Color)Application.Current.Resources["PhoneBackgroundColor"];

if(backgroundColor == "#FF000000") //Dark theme selected
VariableTextColor = RedBrush;
else
VariableTextColor = WhiteBrush;

Another aproach using PhoneDarkThemeVisibility resource:

    /// <summary>
    /// Determines if the application is running in the dark theme
    /// </summary>
    private bool IsDarkTheme
    {
        get
        {
            if (IsDesignMode)
            {
                return true;
            }
            else
            {
                return (Visibility)Application.Current
                    .Resources["PhoneDarkThemeVisibility"] == Visibility.Visible;
            }
        }
    } 
0
votes

The approach described by Richard Szalay didn't work in my case either because I needed it in a UserControl or because of something else, however it is really close to the answer. My project is Silverlight Windows Phone 8.1 project and I'm using Visual Studio 2013 with the latest updates. Probably that was the problem. This is what helped in my case

   <UserControl.Resources>
      <ResourceDictionary>
         <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary  Source="/Application;component/Controls/NumberKeyboard.Dark.xaml" />
            <windows:ThemeSelector>
               <windows:ThemeSelector.Dark>
                  <ResourceDictionary Source="/Application;component/Controls/NumberKeyboard.Dark.xaml" />
               </windows:ThemeSelector.Dark>
               <windows:ThemeSelector.Light>
                  <ResourceDictionary Source="/Application;component/Controls/NumberKeyboard.Light.xaml" />
               </windows:ThemeSelector.Light>
            </windows:ThemeSelector>
         </ResourceDictionary.MergedDictionaries>

         <Style x:Key="KeyboardButton" TargetType="controls:SimpleButton">
            <Setter Property="FontSize" Value="45" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="Margin" Value="0" />
            <Setter Property="Padding" Value="0" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="VerticalAlignment" Value="Stretch" />
         </Style>
         <Style x:Key="NumberButton" TargetType="controls:SimpleButton" BasedOn="{StaticResource KeyboardButton}">
            <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}" />
            <Setter Property="Background" Value="{StaticResource ButtonBrush}" />
         </Style>
         <Style x:Key="ControlButton" TargetType="controls:SimpleButton" BasedOn="{StaticResource KeyboardButton}">
            <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}" />
            <Setter Property="Background" Value="{StaticResource ButtonBrush}" />
         </Style>
         <Style x:Key="ActionButton" TargetType="controls:SimpleButton" BasedOn="{StaticResource KeyboardButton}">
            <Setter Property="Foreground" Value="{StaticResource PhoneBackgroundBrush}" />
            <Setter Property="Background" Value="{StaticResource PhoneForegroundBrush}" />
         </Style>
      </ResourceDictionary>
   </UserControl.Resources>

The key line is <ResourceDictionary Source="/Application;component/Controls/NumberKeyboard.Dark.xaml" /> right before <windows:ThemeSelector>. That line is necessary for the VS designer to display everything right and ThemeSelector overrides the styles in runtime accordingly to the current theme dark or light.