{"id":45,"date":"2012-07-20T08:38:00","date_gmt":"2012-07-20T08:38:00","guid":{"rendered":"http:\/\/tpodolak.com.hostingasp.pl\/blog\/2012\/07\/20\/windows-phone-skinnable-application\/"},"modified":"2016-01-31T00:12:25","modified_gmt":"2016-01-31T00:12:25","slug":"windows-phone-skinnable-application","status":"publish","type":"post","link":"https:\/\/tpodolak.com\/blog\/2012\/07\/20\/windows-phone-skinnable-application\/","title":{"rendered":"Windows Phone &#8211; skinnable application"},"content":{"rendered":"<h3>1. Introduction<\/h3>\n<p>Today, I would like to present my concept of making skinnable application in Windows Phone 7.1. Making a skinnable application in Windows Phone might be a little bit tricky. Unfortunately, WP7 doesn&#8217;t support <i>DynamicResource<\/i> keyword which is a basic tool for making skins in WPF. In order to overcome this inconvenience I decided to write a <i>SkinManager<\/i> for WindowsPhone.<\/p>\n<h3>2. Base view <\/h3>\n<p>As I mentioned before, there is no support for using dynamic resources in WP7, therefore, in order to force a control to change style, we have to assign this style in code behind. It is rather obvious that in a single window\/control there might be quite a lot of other controls whose style also should be changed. That is why, I decided to write controls iterator first.<\/p>\n<pre lang=\"csharp\">\r\npublic class ViewsEnumerator : IEnumerator<FrameworkElement>\r\n{\r\n    private Stack<FrameworkElement> _frameworkElementsStack = new Stack<FrameworkElement>();\r\n    private FrameworkElement _current;\r\n    private readonly FrameworkElement _startingElement;\r\n    \r\n    public ViewsEnumerator(FrameworkElement stargingElement)\r\n    {\r\n        _startingElement = stargingElement;\r\n    }\r\n    \r\n    public void Dispose()\r\n    {\r\n        _current = null;\r\n        _frameworkElementsStack.Clear();\r\n        _frameworkElementsStack = null;\r\n    }\r\n \r\n    #region Implementation of IEnumerator\r\n\r\n    public bool MoveNext()\r\n    {\r\n        if (_current == null)\r\n        {\r\n            _current = _startingElement;\r\n            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(_current); i++)\r\n                _frameworkElementsStack.Push((FrameworkElement)VisualTreeHelper.GetChild(_current, i));\r\n        }\r\n        else\r\n        {\r\n            if (_frameworkElementsStack.Count == 0) return false;\r\n            _current = _frameworkElementsStack.Pop();\r\n\r\n            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(_current); i++)\r\n                _frameworkElementsStack.Push((FrameworkElement)VisualTreeHelper.GetChild(_current, i));\r\n            return true;\r\n        }\r\n        return true;\r\n    }\r\n\r\n    public void Reset()\r\n    {\r\n        _current = null;\r\n        _frameworkElementsStack.Clear();\r\n        _frameworkElementsStack = null;\r\n    }\r\n\r\n    public FrameworkElement Current\r\n    {\r\n        get { return _current; }\r\n    }\r\n\r\n    object IEnumerator.Current\r\n    {\r\n        get { return Current; }\r\n    }\r\n\r\n    #endregion\r\n}\r\n<\/pre>\n<p>In this iterator I used DFS algorithm for searching elements in a tree. Thanks to this piece of code I can take advantage of LINQ's benefits. In the next step I created base classes for views.<\/p>\n<pre lang=\"csharp\">\r\npublic interface IViewBase : IEnumerable<FrameworkElement>\r\n{\r\n}\r\n\r\npublic class ViewBase : UserControl, IViewBase\r\n{\r\n   #region Implementation of IEnumerable\r\n\r\n    \/\/\/ <summary>\r\n    \/\/\/ Returns an enumerator that iterates through the collection.\r\n    \/\/\/ <\/summary>\r\n    \/\/\/ <returns>\r\n    \/\/\/ A <see cref=\"T:System.Collections.Generic.IEnumerator`1\"\/> that can be used to iterate through the collection.\r\n    \/\/\/ <\/returns>\r\n    public IEnumerator<FrameworkElement> GetEnumerator()\r\n    {\r\n        return new ViewsEnumerator(this);\r\n    }\r\n\r\n    \/\/\/ <summary>\r\n    \/\/\/ Returns an enumerator that iterates through a collection.\r\n    \/\/\/ <\/summary>\r\n    \/\/\/ <returns>\r\n    \/\/\/ An <see cref=\"T:System.Collections.IEnumerator\"\/> object that can be used to iterate through the collection.\r\n    \/\/\/ <\/returns>\r\n    IEnumerator IEnumerable.GetEnumerator()\r\n    {\r\n        return GetEnumerator();\r\n    }\r\n\r\n    #endregion\r\n}\r\n<\/pre>\n<h3>3. SkinManager class<\/h3>\n<p>Having prepared basis for skinnable control, let me introduce a custom attribute called the <i>SkinnablePartAttribute<\/i><\/p>\n<pre lang=\"csharp\">\r\n[AttributeUsage(AttributeTargets.Class)]\r\npublic class SkinnablePartAttribute : Attribute\r\n{\r\n    public string ThemePartName { get; set; }\r\n}\r\n<\/pre>\n<p>This attribute should decorate custom controls which should have an ability to change theme\/skin. As you can see, the <i>SkinnablePartAttribute<\/i> has a <i>ThemePartName<\/i> property which holds information about a name of <i>ResourceDictionary<\/i> where styles for the given control ought to be searched. Now, it is time to take a look at a <i>SkinManager<\/i> class. The <i>SkinManager<\/i> class has one public function - <i>ApplySkin<\/i><\/p>\n<pre lang=\"csharp\">\r\npublic static void ApplySkin<TView>(TView view, string skinName)\r\n           where TView : FrameworkElement, IViewBase\r\n{\r\n    foreach (IViewBase control in view.Where(val => val.ImplementsInterfaceOf<IViewBase>()))\r\n    {\r\n        var assemblyName = control.GetType().Assembly.FullName;\r\n        Uri parsedUri;\r\n        var attribute = control.GetType().GetCustomAttributes(typeof(SkinnablePartAttribute), true).SingleOrDefault();\r\n        if (attribute != null && Uri.TryCreate(string.Format(\"\/{0};component\/Themes\/{1}\/{2}.xaml\",assemblyName.Substring(0, assemblyName.IndexOf(\",\", StringComparison.Ordinal)), skinName,(attribute as SkinnablePartAttribute).ThemePartName), UriKind.Relative, out parsedUri))\r\n            ApplySkin(control, parsedUri);\r\n        else\r\n            Debug.WriteLine(string.Format(\"Could not find {0}\/{1}\", skinName,(attribute as SkinnablePartAttribute).ThemePartName));\r\n    }\r\n}\r\n<\/pre>\n<p>This function iterates through all controls which implement a <i>IViewBase<\/i> interface - in other words, the function iterates through our custom controls. If a control is decorated with the <i>SkinnablePartAttribue<\/i>, a new <i>Uri<\/i> is created based on the information from the <i>ThemePartName<\/i> property and from the skinName parameter(I assumed that all dictionaries are located in the Themes directory). In the final step, private function also known as the <i>AppySkin<\/i> function is called. This function looks this way:<\/p>\n<pre lang=\"csharp\">\r\nprivate static void ApplySkin<TView>(TView view, Uri uri, int mergedDictionaryIndex = 0)\r\n            where TView :  IViewBase\r\n{\r\n    var castedView = view as FrameworkElement;\r\n    if(castedView == null) return;\r\n\r\n    var resourceMergedDictionary = castedView.Resources.MergedDictionaries[mergedDictionaryIndex];\r\n    var beforeClearDictionary = resourceMergedDictionary.ToDictionary(key => key.Value, val => new { key = val.Key, value = val.Value });\r\n    castedView.Resources.MergedDictionaries.Remove(resourceMergedDictionary);\r\n    resourceMergedDictionary.Clear();\r\n\r\n    var newStyleDictionary = new ResourceDictionary\r\n    {\r\n        Source = uri\r\n    };\r\n\r\n    castedView.Resources.MergedDictionaries.Insert(mergedDictionaryIndex, newStyleDictionary);\r\n    foreach (var control in view.Where(val => val.Style != null && !val.ImplementsInterfaceOf<IViewBase>()).Where(control =>\r\n        beforeClearDictionary.ContainsKey(control.Style) && newStyleDictionary[beforeClearDictionary[control.Style].key] != null))\r\n        control.Style = newStyleDictionary[beforeClearDictionary[control.Style].key] as Style;\r\n\r\n    beforeClearDictionary.Clear();\r\n}\r\n<\/pre>\n<p>Here, all the magic begins. In the first step, current <i>ResourceDictionary<\/i> is transformed into the standard dictionary. The key of this dictionary is a value of style \u2013 a reference to the style object. In the next step, I created a new <i>ResourceDictionary<\/i> based on the Uri parameter passed to this function. In the last step, another loop over controls is performed. However, this time only controls with the assigned <i>Style<\/i> property are taken into consideration. Then, if the <i>newStyleDictionary<\/i> contains a key of given control style we are ready to swap styles.<\/p>\n<pre lang=\"csharp\">\r\ncontrol.Style = newStyleDictionary[beforeClearDictionary[control.Style].key] as Style;\r\n<\/pre>\n<p>Entire listing of <i>SkinManager<\/i> is presented below<\/p>\n<pre lang=\"csharp\">\r\npublic static class SkinManager\r\n{\r\n    private static void ApplySkin<TView>(TView view, Uri uri, int mergedDictionaryIndex = 0)\r\n        where TView :  IViewBase\r\n    {\r\n        var castedView = view as FrameworkElement;\r\n        if(castedView == null) return;\r\n\r\n        var resourceMergedDictionary = castedView.Resources.MergedDictionaries[mergedDictionaryIndex];\r\n        var beforeClearDictionary = resourceMergedDictionary.ToDictionary(key => key.Value, val => new { key = val.Key, value = val.Value });\r\n        castedView.Resources.MergedDictionaries.Remove(resourceMergedDictionary);\r\n        resourceMergedDictionary.Clear();\r\n\r\n        var newStyleDictionary = new ResourceDictionary\r\n        {\r\n            Source = uri\r\n        };\r\n\r\n        castedView.Resources.MergedDictionaries.Insert(mergedDictionaryIndex, newStyleDictionary);\r\n        foreach (var control in view.Where(val => val.Style != null && !val.ImplementsInterfaceOf<IViewBase>()).Where(control =>\r\n            beforeClearDictionary.ContainsKey(control.Style) && newStyleDictionary[beforeClearDictionary[control.Style].key] != null))\r\n            control.Style = newStyleDictionary[beforeClearDictionary[control.Style].key] as Style;\r\n\r\n        beforeClearDictionary.Clear();\r\n\r\n    }\r\n    \r\n    public static void ApplySkin<TView>(TView view, string skinName)\r\n       where TView : FrameworkElement, IViewBase\r\n    {\r\n\r\n        foreach (IViewBase control in view.Where(val => val.ImplementsInterfaceOf<IViewBase>()))\r\n        {\r\n            var assemblyName = control.GetType().Assembly.FullName;\r\n            Uri parsedUri;\r\n            var attribute = control.GetType().GetCustomAttributes(typeof(SkinnablePartAttribute), true).SingleOrDefault();\r\n            if (attribute != null && Uri.TryCreate(string.Format(\"\/{0};component\/Themes\/{1}\/{2}.xaml\",assemblyName.Substring(0, assemblyName.IndexOf(\",\", StringComparison.Ordinal)), skinName,(attribute as SkinnablePartAttribute).ThemePartName), UriKind.Relative, out parsedUri))\r\n                ApplySkin(control, parsedUri);\r\n            else\r\n                Debug.WriteLine(string.Format(\"Could not find {0}\/{1}\", skinName,(attribute as SkinnablePartAttribute).ThemePartName));\r\n            \r\n        }\r\n    }\r\n}\r\n<\/pre>\n<h3>4. Example of usage<\/h3>\n<p>In order to use the <i>SkinManager<\/i> it is essential to make some preparation. First of all, you have to create <i>Themes<\/i> directory in a project. In this directory there must be separate subdirectories for every skin you would like to use. What is more, in these subdirectories you should place all <i>ResourceDictionaries<\/i> specified in the <i>SkinnablePartAttribute<\/i>. A sample directory structure is shown in the picture below:<br \/>\n<a href=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/DirectoryStructure.png\" rel=\"attachment wp-att-407\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/DirectoryStructure.png\" alt=\"DirectoryStructure\" width=\"303\" height=\"246\" class=\"aligncenter size-full wp-image-407\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/DirectoryStructure.png 303w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/DirectoryStructure-150x122.png 150w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/DirectoryStructure-300x244.png 300w\" sizes=\"auto, (max-width: 303px) 100vw, 303px\" \/><\/a><br \/>\nThe very last step is to make controls (which should be skinnable) inherit from <i>ViewBase<\/i>. Here is example of usage<\/p>\n<pre lang=\"csharp\">\r\nnamespace Joomanji.Chat.Client.Views\r\n{\r\n    [SkinnablePart(ThemePartName = \"ChatWindowSkin\")]\r\n    public partial class ChatWindowView : ViewBase\r\n    {\r\n        public ChatWindowView()\r\n        {\r\n            SkinManager.ApplySkin(this, \"Red\"); \/\/ change skin\r\n        }\r\n    }   \r\n}\r\n<\/pre>\n<p>and screenshots of the same view with different skin<\/p>\n<div style=\"clear: both; text-align: center;\">\n<div style=\"float: left\">\n<a href=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/right.jpg\" rel=\"attachment wp-att-409\"><img decoding=\"async\" src=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/right-159x300.jpg\" alt=\"skinnable application\" width=\"250\" class=\"aligncenter size-medium wp-image-409\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/right-159x300.jpg 159w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/right-80x150.jpg 80w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/right.jpg 375w\" sizes=\"(max-width: 159px) 100vw, 159px\" \/><\/a>\n<\/div>\n<div style=\"float: right\">\n<a href=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/left.jpg\" rel=\"attachment wp-att-408\"><img decoding=\"async\" src=\"http:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/left-158x300.jpg\" alt=\"skinnable application\" width=\"250\" class=\"aligncenter size-medium wp-image-408\" srcset=\"https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/left-158x300.jpg 158w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/left-79x150.jpg 79w, https:\/\/tpodolak.com\/blog\/wp-content\/uploads\/2012\/07\/windows-phone-skinnable-application\/left.jpg 374w\" sizes=\"(max-width: 158px) 100vw, 158px\" \/><\/a>\n<\/div>\n<\/div>\n<div style=\"clear: both;\"><\/div>\n<h3>5. Controls with dynamically changing content<\/h3>\n<p>After some test, it turned out that the mechanism presented above has problems with controls which change their content dynamically. Let me clarify - styling grids, list boxes etc. work fine, however changing row styles and\u3000listboxitem styles are not working properly. In order to overcome this problem you must define a style for a specific target type. Here is an example of usage with the listbox:<\/p>\n<pre lang=\"xml\">\r\n<Style TargetType=\"ListBox\">\r\n    <Setter Property=\"HorizontalContentAlignment\" Value=\"Stretch\"\/>\r\n    <Setter Property=\"VerticalAlignment\" Value=\"Stretch\"\/>\r\n    <Setter Property=\"ItemTemplate\" Value=\"{StaticResource GeneralChatMessageTemplate}\"\/>\r\n<\/Style>\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>1. Introduction Today, I would like to present my concept of making skinnable application in Windows Phone 7.1. Making a skinnable application in Windows Phone might be a little bit tricky. Unfortunately, WP7 doesn&#8217;t support DynamicResource keyword which is a basic tool for making skins in WPF. In order to overcome this inconvenience I decided [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3,44,104,105,30],"tags":[159,190,238,239,240],"class_list":["post-45","post","type-post","status-publish","format-standard","hentry","category-c","category-silverlight","category-skins","category-themes","category-windows-phone","tag-c","tag-silverlight","tag-skins","tag-themes","tag-windows-phone"],"_links":{"self":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/45","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/comments?post=45"}],"version-history":[{"count":4,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/45\/revisions"}],"predecessor-version":[{"id":551,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/posts\/45\/revisions\/551"}],"wp:attachment":[{"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/media?parent=45"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/categories?post=45"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tpodolak.com\/blog\/wp-json\/wp\/v2\/tags?post=45"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}