Blend Bits 7: Be Resourceful

Resources are easy enough to understand.

Lots of elements used in XAML markup have a little dictionary of resources associated with them that can store an object of any type as long as it has a key associated with it (except in one case which I’ll come back to in a different post about Styles).

An element at a particular point in a UI hierarchy defined in XAML can then reference resources using the {StaticResource} markup extension and get the resource resolved. That resolution involves scanning “up” the UI hierarchy looking for an appropriately named resource and that search also includes “application level resources” defined in an app.xaml file.

Dictionaries of resources can be put into separate files and then merged together to form one bunch of resources.

Blend supports all of that. If I create a blank, new Silverlight project then I get by default an App.xaml file and a MainPage.xaml file and over on the Resources Panel/Window I see that I’ve no resources right now;

image

but it’s “interesting” in that it shows me that there are 2 XAML files where resources might be placed and that within my MainPage.xaml it also shows me my UserControl as a place where resources might be put – as far as I know that UserControl will always show up there.

I’m not 100% sure of the algorithm that this Resources panel uses to decide what to show – it seems to “do the right thing” which, as far as I can tell, means that it will show;

  1. The top level UserControl
  2. Any current selection
  3. Any other object that has a resource dictionary that is not empty

Making Resources

Why not make a resource? If I go and draw out a Rectangle on the design surface and set its foreground to some solid colour brush like this lovely blue;

image

then I might well want to re-use that as a brush elsewhere so I can go and click on the “advanced options” box to the right of the Fill value – that is, the little white box to the right in order to raise a menu which lets me “Convert to New Resource”…

image

and Blend will then raise a dialog for me;

image

which allows me to define the key for the resource and also allows me to define it in one of a number of places;

  • App.xaml – global to the application
  • in one of a number of places in the current document ( in this case, MainPage.xaml )
    • NB: the places listed here seem to match those that show up in the resources panel which, I’m sure, is not coincidental Smile
  • in a new or existing resource dictionary

If I select App.xaml for the moment then I see my Resources panel update;

image

which shows me that I have the BlueBrush defined in App.xaml and it also lets me edit that brush resource inline in the resources panel;

image

and it also offers me a 2nd view which shows me which elements are using which resources if I click the little button circled below to switch “tabs”;

image

and it also ( is there no end??!?! ) updates the “advanced options” button next to my Fill value in the Properties panel to a green colour which indicates “this is not a local value, it comes from a resource”;

image

Just to illustrate that I can pretty much make a resource out of anything, I can take the Rectangle’s Width property and do the same thing to make it into a resource as well;

image

and if I follow the same procedure to put this as a resource into App.xaml then I now see 2 resources in there;

image

and, once again I can edit that definition in-line by just typing a different value.

If I wanted to “refactor” my resources so they were perhaps not in App.xaml but were, instead, defined as belonging to the UserControl in my MainPage.xaml then I can do that just by drag/drop;

image

image

Let’s say I’ve got something slightly more complex going on. Let’s say I have these Grids and this Ellipse;

image

and I use the same method to take the pink colour of the Ellipse and turn it into a resource. If I go with the “current document” then the dialog offers me;

image

but if I had some resources already present in (say) the red grid and the green grid then it would offer me;

image

which is the same set of places the Resources panel is showing ( when I’ve no selection made on the artboard );

image

If I wanted to use a resource dictionary instead of going with one of these locations then I could ( for instance ) take a TextBlock like this one;

image

and raise the dialog on one of its properties ( let’s say FontSize – NB: this isn’t a great example because I’d usually use a Style for this );

image

and I can extract that out to a resource dictionary;

imageimageimage

and then the Resources panel updates to show me the new dictionary and that it has been merged into the “global” dictionary owned by my App.xaml;

image

If I had a separate ( Silverlight library ) project in my solution with a reference between the two projects and was working in there as below;

image

then the “make new resource” window will still allow me to put that resource into App.xaml or into the resource dictionary MyResources.xaml both of which actually live in the main project;

image

That "feels” a little odd but I can see circumstances where you’d want to do it. Alternatively, of course, I can put it into the local document or into a new resource dictionary in the library project and then have that dictionary merged into the one in app.xaml.

Using Resources

Once I’ve got a resource, using it is pretty easy. Here, I’ve got a red grid that defines a String resource called “resourceText” and then there’s a green grid that contains a TextBlock;

image

I can drag the resource to the TextBlock if I want to and Blend will ask me what I was hoping to achieve based on the type of the resource in question;

image

or I can visit the property over in the properties window and use the Advanced Options button;

image

and if I had multiple resources available (e.g. at the app.xaml level and at the userControl level ) then it’ll show me all that apply;

image

and if I have more than one project in the solution like this set up;

image

where I’ve got an app referencing a library and both the app and the library have resource dictionaries present and I’ve defined 4 brushes;

  • app.xaml – appLevelRedBrush
  • appResourceDictionary.xaml – appLevelDictionaryPinkBrush
  • libraryResourceDictionary.xaml – libraryDictionaryBlueBrush
  • MainControl.xaml – libraryMainControlGreenBrush

then when I’m looking for a brush resource to fill an ellipse on my MainControl.xaml which is in the library project I see;

image

that is – I see the brush that is locally defined in the same XAML file ( green ) but I also see those that surface themselves at the application level either directly or through merged dictionaries ( one of which is coming from the library itself ).

The resources pane is showing this;

image

Whereas if I was working in the main project on MainPage.xaml then I would see possible brushes for my Ellipse of;

image

as, clearly, the green brush isn’t visible at all outside of the file and project that it was defined in.

So…lots of niceties in the environment around defining and re-using resources Smile