Dear fellow developers:
Metro and Office themes require code to load and initialize the theme resources... and we've gotten used to "blind design" with the base theme and having to run the app to actually see the themed windows and controls.
No Longer!
VS2015 has a new Xaml designer which (finally) has the ability to run code in designmode. For VS2013 and earlier you'll need a bit of extra code and two nuget packages from Fody to achieve the same...
First prep the code:
Public Class ThemeHelper
Shared _IsInitialized As Boolean
Shared Sub Initialize()
If Not _IsInitialized Then
ActiproSoftware.Windows.Themes.ThemeManager.BeginUpdate()
'Register Metro (requires reference to ActiproSoftware.Themes.Metro.Wpf)
ActiproSoftware.Windows.Themes.ThemesMetroThemeCatalogRegistrar.Register()
'Register Office (requires reference to ActiproSoftware.Themes.Office.Wpf)
ActiproSoftware.Windows.Themes.ThemesOfficeThemeCatalogRegistrar.Register()
ActiproSoftware.Windows.Themes.ThemeManager.EndUpdate()
_IsInitialized = True
End If
End Sub
End Class
You can call this code in the constructor of your Application object, or if you're not running a WPF application call it in the constructor of the Control or Window you're designing. Just do it BEFORE InitializeComponents.
Class Application
Public Sub New()
ThemeHelper.Initialize()
End Sub
' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
' can be handled in this file.
End Class
' OR
Class MainWindow
Public Sub New()
ThemeHelper.Initialize()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
End Class
In your window or control's xaml: choose: but if you mix the runtime settings take precedence!
themes:ThemeManager.AreNativeThemesEnabled="True"
themes:ThemeManager.Theme="MetroLight"
themes:ThemeManager.DesignModeAreNativeThemesEnabled="True"
themes:ThemeManager.DesignModeTheme="MetroDark"
Mixing the above DesignMode and Runtime attached properties may not be the best idea.. the designer will show the runtime theme of MetroLight... in my experience it's best the set the DesignTimeTheme only... and leave the runtime theme to the global ThemeManager.
In VS2015:
goto Tools/Options/Xaml Designer/General and check : "Run Project code in XAML designer (if supported)"
Now you will see your control in all it's themed glory right in the designer!
Note: You'll need to rebuild your project if you make changes to the xaml defined theme..
For VS2013:
You'll need the nuget package manager extenstion.
Install Fody ( a package for weaving .Net assemblies)
Install Fody/ModuleInit (https://github.com/Fody/ModuleInit)
My packages.config looks like:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Fody" version="1.29.3" targetFramework="net4" developmentDependency="true" />
<package id="ModuleInit.Fody" version="1.5.8.0" targetFramework="net46" developmentDependency="true" />
</packages>
Insert or update a file called FodyWeavers.xml: Mine looks like:
<?xml version="1.0" encoding="utf-8"?>
<Weavers>
<ModuleInit />
</Weavers>
ModuleInit will add a file called ModuleInitializer.cs to your vb project. Never mind: easily removed and replaced with the translated vb class.
I've dumped all required class in a single file called DesignTimeStuff.vb...
' This could be moved to AssemblyInfo
<Assembly: DesignTimeCode(GetType(Initializer))>
<HideModuleName> Module DesignModeHelper
Function IsInDesignMode() As Boolean
Return System.ComponentModel.DesignerProperties.GetIsInDesignMode(New DependencyObject)
End Function
End Module
''' <summary>
''' This code is called at designtime builds
''' </summary>
''' <remarks></remarks>
Public Class Initializer
Inherits DesignTimeInitializerBase
Protected Overrides Sub Initialize()
Application.InitializeThemes()
End Sub
End Class
''' <summary>
''' ModuleInitializer is required by ModuleInit.Fody (via FodyWeavers.xml)
''' </summary>
''' <remarks></remarks>
Public NotInheritable Class ModuleInitializer
Public Shared Sub Initialize()
If IsInDesignMode() Then
For Each assembly In AppDomain.CurrentDomain.GetAssemblies()
Dim attributes = assembly.GetCustomAttributes(GetType(DesignTimeCodeAttribute), True)
' No need to do anything
For Each attribute In attributes
Next
Next
End If
End Sub
End Class
''' <summary>
''' Specifies a type(class) to be constructed during DesignTime
''' </summary>
''' <remarks></remarks>
<AttributeUsage(AttributeTargets.Assembly, AllowMultiple:=True)> _
Public Class DesignTimeCodeAttribute
Inherits Attribute
Private Shared ReadOnly InitializedTypes As New Dictionary(Of Type, Boolean)()
Public Sub New(typeToConstruct As Type)
If InitializedTypes.ContainsKey(typeToConstruct) Then
Return
End If
InitializedTypes(typeToConstruct) = True
If IsInDesignMode() Then
Activator.CreateInstance(typeToConstruct)
End If
End Sub
End Class
''' <summary>
''' Represents the base class for implementing DesignTime Initializers
''' </summary>
''' <remarks></remarks>
Public MustInherit Class DesignTimeInitializerBase
Public Sub New()
If CanInitialize Then
Initialize()
End If
End Sub
Public ReadOnly Property CanInitialize() As Boolean
Get
Return IsInDesignMode()
End Get
End Property
Protected Overridable Sub Initialize()
End Sub
End Class
HTH..
questions to keepitcool@outlook.com
Jurgen
[Modified 9 years ago]