{"id":24,"date":"2013-09-13T19:40:53","date_gmt":"2013-09-13T17:40:53","guid":{"rendered":"http:\/\/www.winmail-dat.com\/kaplof\/?p=24"},"modified":"2013-09-14T21:31:43","modified_gmt":"2013-09-14T19:31:43","slug":"removing-unused-styles-from-silverlight-projects","status":"publish","type":"post","link":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/","title":{"rendered":"Removing unused styles from Silverlight projects"},"content":{"rendered":"<p>During the conception and development of new applications, designers tend to do lots of styling trials. After some years the application will be trashed with unused resources. This effect doesn&#8217;t only pollute and difficult the development process but also increases the size of your delivery.<\/p>\n<h3>The straw that broke the camel&#8217;s back<\/h3>\n<p>One thing that I hate about Silverlight is the over fluffed default theme.\u00a0 It bounces, explodes and fades like a demo application but for commercial use it is just too much (mostly if your users have crappy machines).<\/p>\n<p>One day I decided to just turn it off. I&#8217;m not a Silverlight expert but I didn&#8217;t want any of the developers &#8220;wasting&#8221; time on such a side task. I knew that the previous designer and front-end developers left a mess in the code, but I couldn&#8217;t imagine how bad it was. For each type of component there was up to 4 different styles plus the default one randomly used through out the code. Most of them were just artifacts of some old prototype and no longer used. It was time for a clean up.<\/p>\n<p>Browsing on the Web I didn&#8217;t find any reasonable solution for finding unused resources in Silverlight projects. There is one application called <a href=\"https:\/\/www.galasoft.ch\/sl4-pistachio\/\">Pistachio<\/a>, but it is too fancy and unusable for big projects. So I decided to write my own simple application.<\/p>\n<h3>Additional reasons<\/h3>\n<p>Cleaning up the styles is not only a way to make your application concise and easier for developers to design new pages. Each single <em>xaml<\/em> file will be added as a text resource directly to your binary file (they can be read inside of your <em>dll<\/em>s via any text editor). Even if the binaries are later on zipped in a <em>xap<\/em> file, the sum of these many-lines-long style files can be significant even after compressing them and sending unused meaningless text resources to all your users doesn&#8217;t seem like a best practice.<\/p>\n<h3>Quick and Dirty but effective<\/h3>\n<p>As mentioned above, I didn&#8217;t want to spend much time on this task. So instead of going into the depths of parsing a <em>xaml<\/em> file, I went to the pragmatic approach of doing string search. Styles like are uniquely identified by a key. If this key is not referenced in any other resource then it is not used. Of course this is not bullet proof but it served my purposes.<\/p>\n<p>The first problem was to read the solution file, as styles may be shared among projects. On .Net 4 you can do some hacking for <a href=\"https:\/\/stackoverflow.com\/questions\/707107\/library-for-parsing-visual-studio-solution-files\">using an internal class for reading solution files,<\/a> but on 3.5 it isn&#8217;t possible. As a .sln file is a pure structured text file, this task is not so difficult.<\/p>\n<pre class=\"brush:csharp\">        public Solution(string filename)\r\n        {\r\n            var lines = File.ReadAllLines(filename);\r\n            foreach (string line in lines.Where(l =&gt; l.StartsWith(\"Project\") &amp;&amp; \r\n                                                     l.Contains(\".csproj\")))\r\n                Projects.Add(ParseProjectLine(line));\r\n        }\r\n\r\n        private string ParseProjectLine(string line)\r\n        {\r\n            var parts = line.Split(',');\r\n            if (parts.Length &lt; 3)\r\n                throw new Exception(\"Could not parse project line \" + line);\r\n            var path = parts[1].Trim();\r\n\r\n            \/\/ Remove quotes\r\n            if (path.StartsWith(\"\\\"\"))\r\n                path = path.Substring(1, path.Length - 2);\r\n\r\n            return path;\r\n        }<\/pre>\n<p>Now the second challenge is to parse the Project files. Project files are xml files and one can use the <em>Microsoft.Build.BuildEngine.Project<\/em> class for reading them. I didn&#8217;t find the usage of this class very straightforward, but after some comings and goings it did the job. For identifying if a project in the solution is a Silverlight one, we cannot rely on the <em>SilverlightApplication<\/em> property as it is not set for Silverlight Class Libraries. The solution was to look for the <em>Microsoft.Silverlight.CSharp.targets <\/em>namespace in the Import section (I&#8217;m sure if this the best approach).<\/p>\n<pre class=\"brush:csharp\">project.Load(projectFilename);\r\nvar property = project.EvaluatedProperties[\"SilverlightApplication\"];\r\n\r\nbool isSl = property != null &amp;&amp; property.Value == \"true\";\r\n\r\nif (!isSl)\r\n{\r\n  isSl = project.Imports.Cast&lt;Import&gt;().Any(n =&gt; \r\n           n.ProjectPath.Contains(\"Microsoft.Silverlight.CSharp.targets\"));\r\n  if (!isSl)\r\n    return;\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<p>Once you have the list of the projects and <em>xaml<\/em> files, you can start playing with the string searches. The first task is to enumerate all the Styles used. Although I hate Regex, this was the fastest solution:<\/p>\n<pre class=\"brush:csharp\">var lines = File.ReadAllText(xaml);\r\n\r\n\/\/ Look for style definition based on Regex match\r\nvar matches = Regex.Matches(lines, \"&lt;(Style|[\\\\w]*Brush).*x:Key=\\\"(?&lt;styleName&gt;[\\\\w]*?)\\\".*&gt;\");\r\nif (matches.Count &gt; 0)\r\n{\r\n  foreach (Match match in matches)\r\n  {\r\n    Group grp = match.Groups[\"styleName\"];\r\n    if (grp != null &amp;&amp; !string.IsNullOrEmpty(grp.Value))\r\n    {\r\n      \/\/ Add style to our collection\r\n      _styles.Add(new KeyValuePair&lt;string, string&gt;(grp.Value, xaml));\r\n    }\r\n  }\r\n}<\/pre>\n<p>The same Regex strategy is used for the identifying if a style is used or not. In this case we are not looking for the style declaration (&lt;Style or &lt;*Brush) but for the usage.<\/p>\n<p>&nbsp;<\/p>\n<h3>The Result<\/h3>\n<p>Without any additional clean-up, I could delete almost half of the styles:<\/p>\n<pre>262 styles found\r\nNon-referenced styles 114:\r\n(...)<\/pre>\n<p>After deleting them I looked for styles that were used only once or twice or that survived the first application restyling. Once this was done I could finally remove the exaggerated Child Window open animation \ud83d\ude42<\/p>\n<p>The full source and binaries can be found here: <a href=\"https:\/\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2013\/09\/CheckSilverlightStyles.zip\">CheckSilverlightStyles<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>During the conception and development of new applications, designers tend to do lots of styling trials. After some years the application will be trashed with unused resources. This effect doesn&#8217;t only pollute and difficult the development process but also increases the size of your delivery. The straw that broke the camel&#8217;s back One thing that [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,8],"tags":[28,27,26],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Removing unused styles from Silverlight projects - Kaplof<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Removing unused styles from Silverlight projects - Kaplof\" \/>\n<meta property=\"og:description\" content=\"During the conception and development of new applications, designers tend to do lots of styling trials. After some years the application will be trashed with unused resources. This effect doesn&#8217;t only pollute and difficult the development process but also increases the size of your delivery. The straw that broke the camel&#8217;s back One thing that [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\" \/>\n<meta property=\"og:site_name\" content=\"Kaplof\" \/>\n<meta property=\"article:published_time\" content=\"2013-09-13T17:40:53+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2013-09-14T19:31:43+00:00\" \/>\n<meta name=\"author\" content=\"Bruno Marotta\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bruno Marotta\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\"},\"author\":{\"name\":\"Bruno Marotta\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891\"},\"headline\":\"Removing unused styles from Silverlight projects\",\"datePublished\":\"2013-09-13T17:40:53+00:00\",\"dateModified\":\"2013-09-14T19:31:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\"},\"wordCount\":699,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#organization\"},\"keywords\":[\"Code optimization\",\"Regex\",\"Silverlight\"],\"articleSection\":[\"Code optimization\",\"Silverlight\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\",\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\",\"name\":\"Removing unused styles from Silverlight projects - Kaplof\",\"isPartOf\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#website\"},\"datePublished\":\"2013-09-13T17:40:53+00:00\",\"dateModified\":\"2013-09-14T19:31:43+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.kopf.com.br\/kaplof\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Removing unused styles from Silverlight projects\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#website\",\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/\",\"name\":\"Kaplof\",\"description\":\"Sharing problems and solutions for software development\",\"publisher\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.kopf.com.br\/kaplof\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#organization\",\"name\":\"Kopf\",\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1\",\"width\":78,\"height\":76,\"caption\":\"Kopf\"},\"image\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891\",\"name\":\"Bruno Marotta\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g\",\"caption\":\"Bruno Marotta\"},\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/author\/bmarotta\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Removing unused styles from Silverlight projects - Kaplof","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/","og_locale":"en_US","og_type":"article","og_title":"Removing unused styles from Silverlight projects - Kaplof","og_description":"During the conception and development of new applications, designers tend to do lots of styling trials. After some years the application will be trashed with unused resources. This effect doesn&#8217;t only pollute and difficult the development process but also increases the size of your delivery. The straw that broke the camel&#8217;s back One thing that [&hellip;]","og_url":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/","og_site_name":"Kaplof","article_published_time":"2013-09-13T17:40:53+00:00","article_modified_time":"2013-09-14T19:31:43+00:00","author":"Bruno Marotta","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Bruno Marotta","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#article","isPartOf":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/"},"author":{"name":"Bruno Marotta","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891"},"headline":"Removing unused styles from Silverlight projects","datePublished":"2013-09-13T17:40:53+00:00","dateModified":"2013-09-14T19:31:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/"},"wordCount":699,"commentCount":0,"publisher":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#organization"},"keywords":["Code optimization","Regex","Silverlight"],"articleSection":["Code optimization","Silverlight"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/","url":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/","name":"Removing unused styles from Silverlight projects - Kaplof","isPartOf":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#website"},"datePublished":"2013-09-13T17:40:53+00:00","dateModified":"2013-09-14T19:31:43+00:00","breadcrumb":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.kopf.com.br\/kaplof\/removing-unused-styles-from-silverlight-projects\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.kopf.com.br\/kaplof\/"},{"@type":"ListItem","position":2,"name":"Removing unused styles from Silverlight projects"}]},{"@type":"WebSite","@id":"https:\/\/www.kopf.com.br\/kaplof\/#website","url":"https:\/\/www.kopf.com.br\/kaplof\/","name":"Kaplof","description":"Sharing problems and solutions for software development","publisher":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.kopf.com.br\/kaplof\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.kopf.com.br\/kaplof\/#organization","name":"Kopf","url":"https:\/\/www.kopf.com.br\/kaplof\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1","width":78,"height":76,"caption":"Kopf"},"image":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891","name":"Bruno Marotta","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g","caption":"Bruno Marotta"},"url":"https:\/\/www.kopf.com.br\/kaplof\/author\/bmarotta\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts\/24"}],"collection":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/comments?post=24"}],"version-history":[{"count":10,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts\/24\/revisions"}],"predecessor-version":[{"id":33,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts\/24\/revisions\/33"}],"wp:attachment":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/media?parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/categories?post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/tags?post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}