.NET Reflector is a great tool. I would wager that most of our loyal readers (all 6 of them 😉 ) already know all about .NET Reflector. But just in case, here is how to get it:
In addition to spying on the code parts of Silverlight assemblies, or verifying the object model of your own custom assemblies, a great little trick you can use with .NET Reflector is to access the genuine XAML that represents a library's generic.xaml file. The generic.xaml file is sometimes referred to as the "theme file", because of its history in WPF, but in Silverlight the concept of "theme" is something of a distraction, so I won't use that word again. I usually just call this thing generic.xaml.
Generic.xaml contains the initial and default template values for all the code-defined controls in the assembly that are supposed to have a UI representation. Basically generic.xaml is an enormous ResourceDictionary, where each keyed item in the dictionary is a separate Style. Each such style is keyed by the TargetType of the control that the style and its enclosed templates are applied to at run time. So, if you have a copy of generic.xaml, and you use a Find operation to find the string key of a type you are interested in, you have a view of the XAML that composites that control by default. Using the default XAML template is the best possible starting point for recreating the template that you might use to retemplate a control. It can also be a useful starting point if you have subclassed the relevant control class, and you want your subclass to be just a slight variation on the behavior and UI representation of an existing control.
Before I get around to touting .NET Reflector, I will first put in the plug for the MSDN Silverlight documentation, which can provide much of this same information but in a different presentation. The default templates for every control we document from the reference perspective actually exist as part of the MSDN documentation. Start from Control Styles and Templates in the TOC. Open up the topic for the particular control you are interested. Take for example TextBox. Each of these pages contain the following information:
- Named parts of the control, if any. Knowing the named parts is important because you must replicate that part (with the same name) in order to not break the base control class' contract behavior.
- Named states of the control that the default template defines. The existing named states each communicate information visually to the control user. Generally any new template should provide states for any state name/case that the default template provided, for the best user experience. You can also add your own new states, if that makes sense based on extra elements or behavior that you add to the template, or a subclassed control.
- The complete XAML of the default template. This includes the XAML of the parts and states; the listings at the start of each Styles and Templates topic is just to make that information easier to find and have a chance to explain the function and purpose of each part/state.
Now, while these MSDN topics are great, sometimes it is interesting to see ALL the templates lined up, to see little variations in compositing of related controls. Or sometimes it is just nice to get "close to the metal" and see the template that is actually invoked rather than rely on the documentation. That in fact is VERY HANDY for periods where you are using Beta or Preview releases, and the documentation might not be caught up yet or unavailable. Plus, the techniques I am about to describe work for ANYONE's control library - third parties, classes from the Silverlight Toolkit, etc. Or even your own, just in case you can't remember your own templates 😉
All this lead-in. Let's finally get to talking about what I titled this post - .NET Reflector and getting generic.xaml!
1. Start .NET Reflector. File/Open the DLL you are interested in. Nearly all the Core classes are defined in System.Windows.dll. Otherwise, the SDK controls are in the several Client library dlls that are installed by Silverlight SDK as reference assemblies.
2. Use the (+) in the tree view to open up just one level. You should see two nodes - one that is the "library" node, with same name as the assembly, and a Resources node.
3. Use the (+) in Resources to open up another level. You should see a level that ends with .g.resources. Open that one up with (+).
4. Here, system.windows will show multiple themes/*.xaml resources. SDK client assemblies will show just one themes/generic.xaml. Double-click either the generic.xaml (for SDK) or specific XAML file you are interested in.
NOTE: At this point you might run into a hitch. .NET Reflector is using a file association for .xaml to tell it what to do. If you have .NET Framework installed, .xaml might be associated with the XBAP deployment model for WPF, and will try to open as hosted PresentationHost XAML content in Internet Explorer. Not useful! If this happens, you should use the Windows Explorer view options to change the .xaml association to your favorite text editor, or possibly even to VS.
OK, if that hitch got you, try again. Voila! Using the associated editor, you now can see the template XAML direct from the assembly that you are already using for your reference assembly purposes or perhaps for deploy purposes too. If you do it this way there is pretty much no chance that the template you are trying to copy is somehow not correspondent to the code, because they are coming from the same assembly. Well, no chance so long as the assembly authors knew what they were doing.
Final note - the System.Windows XAML resources don't have "pretty print" formatting niceties, such as line breaks between elements; they were probably trying to eke out every last byte of possible savings in the Silverlight core download size. It might be useful to view these in a deliberate XML-aware editor so that they are easier to read, or even to do a search-replace of > for >\n in a copy to at least get per-element line breaks. Or, the SDK topics have better formatting.
And here is the See Also, which is how we SDK writers end our writing when it's time to wrap it up and go get coffee. Now really that's the template for an actual SDK topic we are writing and not a blog post. But it is a hard habit to break ...