Shiny Orangy

Sorry that I've been pretty silent for the last couple of weeks. I was at PDC for a week and then took a week and a half off to visit my wife's family in Ithaca. Well, as you can imagine, this meant a lot of flying and I used my time on the plane to build some control styles. The two I've made so far turned out pretty nicely, so I've posted them for your styling pleasure. So far, I've only created two styles: one for Button and one for TabControl, but more should be coming. These work with the September CTP bits (which are the same bits handed out at the PDC).

You can download the styles here.

Explanation

Some explanation about the styles is in order. These are not general purpose control styles. Depending on what you try to do, some things may not work out quite as you would expect. So, here are some of the limitations and my reasoning behind them:

Button Content

I wanted to a drop shadow on the content inside of the Button and TabItem. It turns out that we do have a drop shadow bitmap effect which would be a very responsible way to implement this effect. I hit two problems with this, though. The biggest problem is that the drop shadow effect simply doesn't look good the PDC bits. Don't worry, though, it's getting better. In fact, it looks much nicer in our current internal builds.

The other issue (which turned out to be a red herring) is that the hover effect is supposed simulate a light inside of the button. In the real world, this light should overpower the drop shadow. So, I wanted the highlight to sit between the content and its drop shadow. This was a red herring, though, because I realized that If I used the canned drop shadow effect, I could just turn it off when the highlight was on.

Nevertheless, for the time being I've implemented this by using two ContentPresenters in the template and adjusting the opacity and using a blur effect on the second of the two. This actually looks pretty nice, but does have some undesirable consequences.

First, it means that you only get a drop shadow if your content is a data type (as opposed to UIElements). Fortunately, strings are data, not UI elements. So this works perfectly with a string as your content. Data works because WPF doesn't natively know how to display your data. Instead it has to spin up the appropriate data template. If you don't provide a data template (as is probably the case for string content), then WPF creates one for you which is just a TextBlock with its content set to the data object's .ToString().

If your button has a UIElement as its content, on the other hand, that element already exists and can only be displayed in once place. There is no template to create, WPF just shows the element. It turns out that the ContentPresenter wins and, in our case, the last ContentPresenter is the primary ContentPresenter, so things work pretty well, just no dropshadow.

Second, if you set the Foreground property on the Button, it will change the Foreground of the dropshadow as well. There is a simple workaround for this. ContentPresenter doesn't have a Foreground property so Foreground just inherits from its parent. ContentControl, on the other hand, does. So,instead of using a ContentPresenter for the blurred content, you can use a ContentControl and set the Foreground property on it black or whatever color you want the shadow to be. I didn't do this because my app never sets Foreground, but it would be easy to do if you needed it.

Highlight Color

You'll notice that the Button appropriately responds to changes to the Background property. Unfortunately, not all backgrounds look good with the MouseOver highlight. There is no property on button that can be used for highlight color, so there is no easy way to make this customizable. My solution was to use a dynamic resource for the brush on the highlight element. By making this resource dynamic, a user of the control has the ability to redefine the resource more locally. I've called the resource brush 'HighlightGradient.' To change it, all you have to do is redefine locally. You can define it in the resource section for the button itself, or in the resource for any shared parent if you want to use it among multiple buttons. I'm curious to know what people think about this approach is this a useful way to provide customization entry points that go beyond properties on the control?

Animation in TabItem

I wanted the TabItems to be animated when transitioning from Selected to Unselected. I couldn't do it though. The problem is that all animations are triggered by events in these bits. While we do have an event for Selected and Unselected, that event can potentially be fired before the template get applied. If I try to refer to a target element in the Storyboard before the template is applied, it obviously can't find the element and things blow up.

I could work around this by animating the background directly. I haven't done that for now, but it should work. Maybe a future release...


Published

Discussion

Loading... Show

Previous