State, Element, and Storyboard Pickers
       by kirupa  |  25 November 2009

The Expression Blend Properties Inspector is something you become introduced to very quickly. It is the giant panel usually on the right-hand side of the Blend interface that you use to view and set values on properties:

[ I, for one, welcome our new Properties Inspector overlord ]

The Properties Inspector is fairly intelligent. It exposes any properties your selected item or items exhibit, and for each property, it uses a value picker appropriate for the type of property it is dealing with. If you took a snapshot of any particular area of the Properties Inspector, you'll see a variety of value pickers in play:

[ the right value picker for the right property is my motto ]

From the above screenshot, the Margin property has a value picker made up of four number editors, the Tooltip and Button properties are nothing more than simple text fields, and the ClickMode property is a combobox containing values that you can select from.

Depending on the type of the property, Blend will automatically choose to use the best value picker for the job. The reason is that Blend has hardcoded a lot of the metadata associated with what value picker to display for which particular type. This means you get the right value picker almost for free almost all the time. That's almost awesome.

The State, Element, and Storyboard Pickers
The number of times I mentioned the word "almost" in the previous paragraph should give you pause. While a property of type enum will always display a combobox, a property of type bool will always display a checkbox, a property of type string will always display a textfield, etc., there are times where you want to override the default value picker with something more elaborate.

For example, the name of an element is nothing more than a string. By default, a property of type string will just get a textfield in Blend's Properties Inspector. While that allows you to squeak by with minimum functionality, wouldn't it be nicer if when you wanted the element name, we provide a visual picker (pick whip) that you can use to visually select the element you are interested in? Or when it comes to working with Storyboards, wouldn't it be nice if you could just pick from a list of Storyboards you already have instead of manually typing the name in. In a similar vein as Storyboards, wouldn't it be great to get a list of all States that you currently have access to without typing it in manually?

If you answered Yes to any of the preceding questions, then you are in luck. With the Behaviors feature introduced in Blend 3, several of our behaviors contain properties that use some custom State, Element, and Storyboard value pickers to return a string value. Fortunately, these value pickers were made extensible and usable outside of the world of behaviors! Using these pickers is sort of straightforward, so let's look at how you would use them.

First, you need some properties that you can use these pickers with. In your code, you probably have some properties declared, and they may look as follows:

public string MyState
{
get;
set;
}
 
public string MyElementName
{
get;
set;
}
 
public string MyStoryboard
{
get;
set;
}

Note
For the sake of brevity I am using simple properties, but everything you are learning will work with dependency properties as well.

If you look at these properties in the Properties Inspector, things will look as follows:

[ for string properties, you get a very simple textfield as your value picker ]

Because these properties are all of type string, the Properties Inspector displays a simple textfield where you can type in your string values. What we want to do is overwrite the default behavior by having the MyElementName property display the Element Name value picker, the MyState property display the State Name picker, and the MyStoryboard property display the Storyboard Name picker.

To do this, you  will need to add a reference to an assembly that contains what we need to know about these pickers. Look in your Projects panel and expand the References folder. Look and see if you see System.Windows.Interactivity.dll displayed. If you do not see it, right click on the References folder and select Add Reference:

[ add a reference to the missing assembly ]

Once you have done that, the Add Reference dialog will appear. Navigate to either {Program Files}Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\Silverlight for Silverlight or {Program Files}\Microsoft SDKs\Expression\Blend 3\Interactivity\Libraries\WPF\ for WPF and select System.Windows.Interactivity.dll. Click on Open to add this reference and to close the dialog.

Your references folder will now contain a reference to the System.Windows.Interactivity.dll you just added:

[ your newly added reference will appear now ]

Now that you have added this reference, go back to the code file where you have your properties defined. At the top where the using statements have been defined, go ahead and add the following:

using System.Windows.Interactivity;

Once you have done this, all you have to do is specify which picker you want for each property. This is handled by an attirbute you define on the property itself. The attribute is called CustomPropertyValueEditorAttribute, and it takes an enum from CustomPropertyValueEditor as its argument.

The CustomPropertyValueEditor enum contains the following values: Element, StateName, Storyboard.

Combining all of this, let's look at what our above properties will now look like when attributed to use the appropriate value picker:

[CustomPropertyValueEditorAttribute(CustomPropertyValueEditor.StateName)]
public string MyState
{
get;
set;
}
 
[CustomPropertyValueEditorAttribute(CustomPropertyValueEditor.Element)]
public string MyElementName
{
get;
set;
}
 
[CustomPropertyValueEditorAttribute(CustomPropertyValueEditor.Storyboard)]
public string MyStoryboard
{
get;
set;
}

Notice that each type has the appropriate value from CustomPropertyValueEditor chosen. If you build your project (Ctrl + Shift + B or Project | Build) and take a look at your Properties Inspector where these three properties live (in the usercontrol instance more than likely), you should see something like this:

[ notice that you now have the custom value pickers you defined ]

What used to be boring string editors are now the custom value pickers that allow you to more easily gain access to an element name, a state name, or a storyboard name.

Conclusion
Hopefully this fun little article gave you a quick overview of the Properties Inspector and how you can override the default value pickers to provide something more elaborate. While I only discussed the Element, State, and Storyboard pickers, there are similar attributes that you can set on properties to gain more specialized pickers.

In the end, all that is returned by the three pickers that you used is a string value. You may be wondering whether it is really worth all of this additional steps just so you save time from having to memorize a name from another part of the UI and type it in manually. The answer to that question depends entirely on you or who your intended audience is for this property. With respect to the element, state, and storyboard pickers, while you only get a string value at the end, there are some nice benefits you gain indirectly.

If you refer to a state, element, or storyboard and end up renaming something somewhere down the line, any referenced object will automatically be renamed in the Properties Inspector. This magic, also known as referential integrity, is something you only have when you set the values using the custom value pickers. If you think that is cool, we show a lot more favoritism to the element name value picker. If you use the pick whip to select an unnamed element, Blend will name the element for you automatically. Pretty cool, ehh?

If you would like to see a working version of my example, feel free to download the source files below:

Download Source Files

Once you have opened your project, select the blue rectangle usercontrol and look in the Miscellaneous category where the MyElementName, MyState, and MyStoryboard properties have been defined.

Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!

Kirupa's signature!




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.