unfortunately, some Telerik controls doesn't accept the dynamic change of the theme: some just
Namespace OrdinaSoft.Windows.Controls;
(* Extensions of the Telerik Theme class.
Author: OrdinaSoft
Patrick Lanz
Lausanne
info@ordinasoft.ch
First version: February 17, 2012
*)
Interface
Uses
System.Collections.Generic,
System.Reflection,
System.Windows,
System.Windows.Controls,
System.Windows.Media,
Telerik.Windows.Controls;
(*---------------------------------------------------------------------------------------------*)
Type
/// <summary>
/// Extensions of the Telerik
/// class.
/// </summary>
/// <remarks>
/// This class defines a method that lets change the theme of the application at run-time.
/// </remarks>
osTheme = Public Class (
Theme
)
Private Class
{-- Field --}
/// <summary>
/// Set of the forbidden classes: those on which we must not set the theme.
/// </summary>
ForbiddenClassesNames : HashSet <String>; ReadOnly;
Private
{-- Class constructor --}
/// <summary>
/// Initializes the static data of the class.
/// </summary>
Class Constructor;
{-- Methods --}
/// <summary>
/// Traverse the visual tree from a given object and set the theme on encountered
/// objects.
/// </summary>
/// <param name="Root">
/// Root from which we must traverse the visual tree. Can be <b>null</b>.
/// </param>
/// <param name="NewTheme">The new application theme. Can be <b>null</b>.</param>
Class Method ChangeTheme (Root : DependencyObject; NewTheme : Theme);
/// <summary>
/// Gets a value that indicates whether an object is of a forbidden type.
/// </summary>
/// <param name="Obj">The object to check.</param>
/// <returns>
/// <b>true</b> if <paramref name="Obj" /> is a forbidden type;<br />
/// otherwise, <b>false</b>.
/// </returns>
/// <remarks>
/// <para>
/// An object is of a forbidden type if the name of its type, or the name of the type
/// of one of its ancestors is in <see cref="ForbiddenClassesNames" />.
/// </para>
/// <para>
/// We check the name of the type and not the type, because we can support types
/// without loading the supporting assemblies.
/// </para>
/// </remarks>
Class Method IsForbiddenType (Obj : DependencyObject) : Boolean;
Public
{-- Method --}
/// <summary>
/// Changes the application theme at run-time.
/// </summary>
/// <param name="NewTheme">The new application theme. Can be <b>null</b>.</param>
/// <remarks>
/// In addition to setting the application theme, this method will change the theme of
/// all the controls in the application.
/// </remarks>
Class Method ChangeApplicationTheme (NewTheme : Theme);
End;
(*---------------------------------------------------------------------------------------------*)
Implementation
(*---------------------------------------------------------------------------------------------*)
(* Class constructor. *)
// <summary>
// Initializes the static data of the class.
// </summary>
Class Constructor osTheme;
Begin
ForbiddenClassesNames := New HashSet <String>;
ForbiddenClassesNames.Add ('System.Windows.Controls.UserControl' );
ForbiddenClassesNames.Add ('Telerik.Windows.Controls.RadDocking' );
ForbiddenClassesNames.Add ('Telerik.Windows.Controls.RadPane' );
ForbiddenClassesNames.Add ('Telerik.Windows.Controls.RadPanelBar' );
ForbiddenClassesNames.Add ('Telerik.Windows.Controls.RadPanelBarItem' );
ForbiddenClassesNames.Add ('Telerik.Windows.Controls.RadPaneGroup' );
ForbiddenClassesNames.Add ('Telerik.Windows.Controls.RadSplitContainer')
End;
(*---------------------------------------------------------------------------------------------*)
(* Forbidden types management. *)
// <summary>
// Gets a value that indicates whether an object is of a forbidden type.
// </summary>
// <param name="Obj">The object to check.</param>
// <returns>
// <b>true</b> if <paramref name="Obj" /> is a forbidden type;<br />
// otherwise, <b>false</b>.
// </returns>
// <remarks>
// <para>
// An object is of a forbidden type if the name of its type, or the name of the type
// of one of its ancestors is in <see cref="ForbiddenClassesNames" />.
// </para>
// <para>
// We check the name of the type and not the type, because we can support types
// without loading the supporting assemblies.
// </para>
// </remarks>
Class Method osTheme.IsForbiddenType (
Obj : DependencyObject
) : Boolean;
Begin
If Assigned (Obj) Then Begin
Var &Type := Obj.GetType;
Repeat
If ForbiddenClassesNames.Contains (&Type.FullName) Then
Exit True;
&Type := &Type.BaseType
Until Not Assigned (&Type)
End; {Assigned (Obj)}
Exit False
End;
(*---------------------------------------------------------------------------------------------*)
(* Application theme. *)
// <summary>
// Changes the application theme at run-time.
// </summary>
// <param name="NewTheme">The new application theme. Can be <b>null</b>.</param>
// <remarks>
// In addition to setting the application theme, this method will change the theme of
// all the controls in the application.
// </remarks>
Class Method osTheme.ChangeApplicationTheme (
NewTheme : Theme
);
Begin
StyleManager.ApplicationTheme := NewTheme;
ChangeTheme (Application.Current.RootVisual, NewTheme)
End;
// <summary>
// Traverse the visual tree from a given object and set the theme on encountered
// objects.
// </summary>
// <param name="Root">
// Root from which we must traverse the visual tree. Can be <b>null</b>.
// </param>
// <param name="NewTheme">The new application theme. Can be <b>null</b>.</param>
Class Method osTheme.ChangeTheme (
Root : DependencyObject;
NewTheme : Theme
);
Begin
If Not Assigned (Root) Then
Exit;
// Check for controls on which we can't set the theme.
If Not IsForbiddenType (Root) Then
StyleManager.SetTheme (Root, NewTheme);
{-- Telerik.Windows.Controls.RadDocking --}
// With Matching Control := Telerik.Windows.Controls.RadDocking (Root) Do
// ChangeTheme (DependencyObject (Control.DocumentHost), NewTheme);
{-- System.Windows.Controls.ItemsControl --}
With Matching Control := System.Windows.Controls.ItemsControl (Root) Do Begin
For Matching Item : DependencyObject In Control.Items Do
ChangeTheme (Item, NewTheme);
Exit
End; {With Matching Control := System.Windows.Controls.ItemsControl (Root)}
{-- Control with a header --}
With Matching PropInfo := Root.GetType.GetProperty ('Header') Do
ChangeTheme (DependencyObject (PropInfo.GetValue (Root, Nil)), NewTheme);
{-- System.Windows.Controls.ContentControl --}
With Matching Control := System.Windows.Controls.ContentControl (Root) Do Begin
ChangeTheme (DependencyObject (Control.Content), NewTheme);
Exit
End; {With Matching Control := System.Windows.Controls.ContentControl (Root)}
{-- System.Windows.Controls.Border --}
With Matching Control := System.Windows.Controls.Border (Root) Do Begin
ChangeTheme (Control.Child, NewTheme);
Exit
End; {With Matching Control := System.Windows.Controls.Border (Root)}
{-- Traverse the children --}
For ix : Int32 := 0 To VisualTreeHelper.GetChildrenCount (Root) - 1 Do
ChangeTheme (VisualTreeHelper.GetChild (Root, ix), NewTheme)
End;
(*---------------------------------------------------------------------------------------------*)
End.
When a new RadControls version corrects some of the problems, I will update the code.
I hope it will help you.