Skip to main content
All docs
V25.1
  • Support DevExpress Themes in Custom WPF Controls

    • 6 minutes to read

    DevExpress WPF Controls ship with 30+ built-in themes you can apply to Standard WPF Controls.

    Unlike standard controls, custom WPF components ignore DevExpress themes. To adapt your custom controls to DevExpress themes, use the techniques described in this topic.

    Note

    Techniques described in this topic do not apply to Lightweight Themes. To apply a Lightweight Theme to a custom control, use the LWThemeValueExtension.

    Refer to the following section for more information: Set Theme-Specific Values in XAML.

    Create Theme-Specific Default Styles

    To support multiple DevExpress themes, define a default style for your custom control for each target theme. Use the DefaultStyleThemeKey markup extension to associate each target style with your custom control type and DevExpress theme.

    The following code example defines a style applied to CustomControl when the DeepBlue DevExpress theme (default) is active:

    <Style BasedOn="{StaticResource {x:Type local:CustomControl}}"
           TargetType="{x:Type local:CustomControl}"
           x:Key="{dxt:DefaultStyleThemeKey ThemeName=DeepBlue,
                   Type={x:Type local:CustomControl},
                   TypeInTargetAssembly={x:Type local:MainWindow}}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="Foreground" Value="Blue" />
        <Setter Property="Background" Value="SkyBlue" />
    </Style>
    

    Specify the TypeInTargetAssembly property to identify the assembly that contains default styles for your control. Assign this property to any CLR type in the same assembly (to allow the framework to locate the target assembly).

    Note

    Leave the TypeInTargetAssembly property unspecified if both custom controls and corresponding styles are located in the same assembly. If you store classes in a separate assembly, refer to the assembly using any type defined within it (for example, a marker class).

    Place all default styles (including theme-specific) in the Themes/Generic.xaml resource dictionary of your control assembly. Override the control’s DefaultStyleKey in a static constructor to define your Generic.xaml styles as default:

    public class CustomControl : Control {
        static CustomControl() {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl),
                new FrameworkPropertyMetadata(typeof(CustomControl)));
        }
        // Your control implementation
    }
    

    If you store a custom control in a separate assembly, apply the DxThemeInfo attribute to the control in the AssemblyInfo.cs file as follows:

    // In AssemblyInfo.cs of the custom control assembly:
    [assembly: DevExpress.Xpf.Core.DXThemeInfo(typeof(CustomControl))]
    

    The DxThemeInfo attribute ensures that the DevExpress ThemeManager will include your assembly theme resources.

    Advantages

    • You can fully define control appearance in each theme. In addition, you can ship different ControlTemplate for individual themes.

    • If a style for the active theme is not found, the control falls back to the default style.

    Limitations

    • You must create a separate style for each theme (and each custom control).

    • Theme-specific default styles are associated with a custom control type - all control instances always use the same style. You cannot assign different theme styles to individual control instances unless you override DefaultStyleKey.

    Use DevExpress Theme Resources in Your Style

    You can reference built-in DevExpress theme resources (for example, brushes or colors) directly in your control style using the ThemeResource markup extension. The extension allows the control to load values from the selected theme on demand. You can use the ThemeResource to obtain palette colors as described in the following section: Use Palette Resources.

    <Window ...
        xmlns:dxi="http://schemas.devexpress.com/winfx/2008/xaml/core/internal">
        <Style TargetType="{x:Type local:CustomControl2}">
            <Setter Property="Background"
                    Value="{dxi:ThemeResource {dxt:FloatingContainerThemeKey ResourceKey=FloatingContainerBackground}}" />
            <Setter Property="Foreground"
                    Value="{dxi:ThemeResource {dxgt:GridColumnHeaderThemeKey ResourceKey=GroupHeaderCaptionForeground}}" />
        </Style>
    </Window>
    

    You can override these resources for individual themes:

    <SolidColorBrush x:Key="{dxt:FloatingContainerThemeKey ResourceKey=FloatingContainerBackground, ThemeName=MetropolisDark}"
                     Color="Red" />
    

    Advantages

    • You do not need to define an individual style for each theme.

    • Works without overriding DefaultStyleKey.

    • Automatically adapts to the current theme.

    • Allows local overrides for individual themes.

    Limitations

    • Requires DevExpress resource keys.

    • Some resources may be missing in a specific theme (you need to define missing resources).

    • Best for individual style properties (for example, brushes) rather than complete control templates.

    Define Custom Theme Resource Keys

    You can define custom keys for theme-aware resources instead of using built-in DevExpress resource keys. This technique allows you to define a personalized set of color resources and manage every aspect of UI appearance across themes.

    Declare a custom theme key extension in C#:

    public class ThemeResourcesThemeKeyExtension : ThemeKeyExtensionBase<ThemeResourcesThemeKeys> {
        public override Assembly Assembly {
            get {
                return TypeInTargetAssembly != null ? TypeInTargetAssembly.Assembly : GetType().Assembly;
            }
        }
    }
    
    public enum ThemeResourcesThemeKeys {
        Background,
        Foreground
    }
    

    Use these keys to define resources:

    <!-- Default theme resources -->
    <SolidColorBrush x:Key="{local:ThemeResourcesThemeKey ResourceKey=Background}" Color="LightBlue" />
    <SolidColorBrush x:Key="{local:ThemeResourcesThemeKey ResourceKey=Foreground}" Color="DarkBlue" />
    
    <!-- MetropolisDark theme overrides -->
    <SolidColorBrush x:Key="{local:ThemeResourcesThemeKey ResourceKey=Background, ThemeName=MetropolisDark}" Color="Black" />
    <SolidColorBrush x:Key="{local:ThemeResourcesThemeKey ResourceKey=Foreground, ThemeName=MetropolisDark}" Color="Orange" />
    

    Use these resources in your control style:

    <Window ...
        xmlns:dxi="http://schemas.devexpress.com/winfx/2008/xaml/core/internal">
        <Style TargetType="{x:Type local:CustomControl3}">
            <Setter Property="Background" Value="{dxi:ThemeResource {local:ThemeResourcesThemeKey ResourceKey=Background}}" />
            <Setter Property="Foreground" Value="{dxi:ThemeResource {local:ThemeResourcesThemeKey ResourceKey=Foreground}}" />
        </Style>
    </Window>
    

    Advantages

    • Full control over color values.

    • Reusable across multiple controls.

    Limitations

    • You need to define values for every theme.

    Use BackgroundPanel to Inherit Theme Colors

    If you need to apply theme-specific Background and Foreground colors to your control, place a BackgroundPanel inside its ControlTemplate. This panel applies current theme colors to the background and all child UI elements.

    <ControlTemplate TargetType="{x:Type local:CustomControl4}">
        <Border BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}">
            <dx:BackgroundPanel>
                <TextBlock HorizontalAlignment="Center"
                           VerticalAlignment="Center"
                           Text="{TemplateBinding Text}" />
            </dx:BackgroundPanel>
        </Border>
    </ControlTemplate>
    

    This pattern ensures that text content inherits correct colors without explicit references to specific brushes or resources. If you place the BackgroundPanel property in your control, you do not need to define or use theme-specific resources.

    Advantages

    • Automatically applies theme-specific colors without additional bindings.

    • Does not require resource dictionaries or markup extensions.

    • Can be used inside templates, UserControls, or Windows.

    Limitations

    • Applies only to Background and Foreground properties.

    • Requires changes to the control’s template.

    • Prevents Background and Foreground property value changes in markup or code.

    Bind to ThemeManager.ThemeName

    To change control appearance based on the active theme name, bind a control property (for example, Background or Style) to the ThemeManager.ThemeName property and use triggers or converters to change control appearance based on the active theme.

    Use DataTrigger

    <Style TargetType="{x:Type local:CustomControl5}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(dx:ThemeManager.TreeWalker).ThemeName,
                                           RelativeSource={RelativeSource Self}}"
                         Value="MetropolisDark">
                <Setter Property="BorderBrush" Value="DarkGray" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    

    Use Value Converter

    <dxmvvm:ObjectToObjectConverter x:Key="ThemeNameToForegroundConverter">
        <dxmvvm:MapItem Source="DeepBlue" Target="DarkBlue" />
        <dxmvvm:MapItem Source="MetropolisDark" Target="Orange" />
    </dxmvvm:ObjectToObjectConverter>
    
    <Setter Property="Foreground"
            Value="{Binding Path=(dx:ThemeManager.TreeWalker).ThemeName,
                            RelativeSource={RelativeSource Self},
                            Converter={StaticResource ThemeNameToForegroundConverter}}" />
    

    This technique is useful when you need to apply different values based on specific theme names.

    Advantages

    • You can map any theme names to any visual value.

    • You can use binding to apply complex rules or templates.

    • Does not require predefined resource keys.

    Limitations

    • Appearance changes depend on explicit theme name strings (for example, "DeepBlue", "Office2019Colorful").

    • You need to maintain your implementation for each supported theme.

    • Theme-based conditions increase XAML structure complexity and make custom style more difficult to maintain.

    See Also