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.