Customizing the selected item in a ListBox

July 30, 2007

This blog post demonstrates how to make the selected ListBoxItem in a ListBox display differently than unselected items.  We will see how to add an extra Button to the selected item, but you can add whatever you want by using the technique shown below.  This is what the demo app looks like when you run it and select an item:

Customized SelectedItem (screenshot)

The trick is to set the ListBox’s ItemTemplate to a DataTemplate which knows when to expose the extra visuals for the selected item(s).  Here’s an example of a template which knows how to do that:

 Customized SelectedItem (template)

That DataTemplate creates two Grids.  The outer Grid has two rows: the top row is for the normal item content, and the bottom row hosts the selected item’s extra content.  The inner Grid is in the bottom row.  That inner Grid has a Style which knows when to hide itself (i.e. when the ListBoxItem is not selected).

Here’s a ListBox which consumes that template:

 Customized SelectedItem (ListBox)

Download the demo project here: Customized SelectedItem (Demo) Be sure to change the file extension from .DOC to .ZIP and then decompress it.


Article about creating skinned UIs

July 27, 2007

I just published a new WPF article to CodeProject.  It explains the basics how to design and implement a “skinned” user interface, which means that you can very easily apply different visual styles to a UI at compile-time or runtime.  If you’re interested in this topic, here’s a link to the article: http://www.codeproject.com/useritems/SkinningInWPF.asp


Chris Anderson on WPF

July 27, 2007

An interview with Chris Anderson, one of the chief architects of WPF, was recently posted here.  It is a very interesting 24 minute discussion about WPF.  Anderson provides insight into why WPF was created, what the platform offers for developers and for architects, how and why teams should migrate to WPF, along with several other topics.


A lightweight alternative to DropShadowBitmapEffect

July 24, 2007

This blog post reviews how to create drop shadows around WPF elements in a way which does not have a noticeable impact on an application’s UI performance.

One of the biggest letdowns about the first version of WPF is the fact that bitmap effects are so terribly slow.  The most commonly used bitmap effect is the one which creates a drop shadow around an element; the DropShadowBitmapEffect.  If you start using that class to create drop shadows you will soon find your UI performance suffering immensely.  This is a shame considering how visually appealing a well-placed drop shadow can be.

Here is a screenshot which shows a ListBox with a drop shadow.  The drop shadow was created by adding a DropShadowBitmapEffect to the ListBox’s BitmapEffects collection.

Lightweight DropShadows (using DropShadowBitmapEffect)

If you were to repeatedly resize that Window, you would find that the rendering of the ListBox flickers and is slow.  Why?  The problem is that bitmap effects are not hardware accelerated, and they can execute quite often.  WPF’s support for bitmap effects requires them to be created in unmanaged code (usually C++).  There is currently no way to hardware accelerate those unmanaged routines.  I suppose it is possible to write your own bitmap effects which run themselves on a graphics card’s GPU, but that is way beyond the scope of this post!!

Fortunately there is an easy way to create drop shadows around WPF elements which does not incur any noticeable performance overhead.  The trick is to decorate an element with a SystemDropShadowChrome element.  SystemDropShadowChrome does not have nearly as many settings that you can adjust, but it provides a decent drop shadow for many situations.  Here’s a screenshot of a ListBox which is decorated with that element:

Lightweight DropShadows (usign SystemDropShadowChrome)

SystemDropShadowChrome lives in an obscure assembly and namespace.  If you want to use it, you must add a reference to one of the PresentationFramework.* assemblies (there are currently .Aero, .Luna, .Royale, and .Classic).  You will find the class in the Microsoft.Windows.Themes namespace. 

Each of the PresentationFramework.* assemblies has its own version of the SystemDropShadowChrome class, but after checking them out in Reflector I found out that they are all exactly the same.  Someone must have written the class once, and then pasted it into each of those assemblies.  So, there is no need to worry about choosing the “right” class to use at runtime, based on the user’s current operating system theme settings.  Any one of them will do.

In this post’s demo application I chose to reference the PresentationFramework.Aero assembly, as seen below:

Lightweight DropShadows (assembly references)

Once you have the assembly reference in place, you need to map the Microsoft.Windows.Themes namespace in your XAML file, like this:

xmlns:aero=”clr-namespace:Microsoft.Windows.Themes; assembly=PresentationFramework.Aero”

At that point, it’s simply a matter of wrapping an element in a SystemDropShadowChrome element, and perhaps setting its Color and/or CornerRadius properties.  Here is the XAML which does this in the demo project:

Lightweight DropShadows (XAML)

To read another perspective on the SystemDropShadowChrome class, read here.

Download the demo project here: Lightweight DropShadows (demo project)  Be sure to change the file extension from .DOC to .ZIP and then decompress it.


Stretching Content in an Expander Header (take two)

July 18, 2007

A while ago I posted a blog entry called Stretching Content in an Expander Header which discussed a way to make the content of an Expander’s header occupy all available space in the header area.  The solution I proposed back then required the use of some code to do the trick.  Today a fellow by the name of Patrick Jones posted a comment which shows a clean solution.  His solution still requires the use of code.

After reading over his sample I realized that it is possible (and easy) to implement the functionality without writing any code at all.  The original post has been updated to show the XAML-only solution, which I like the best out of all three options (if you do not care that the header element will be clipped on the righthand side).  Here’s the relevant XAML snippet:

<Expander>
  <Expander.Header>
    <TextBlock
      Text=”I am header text…”
      Background=”Blue”
      Width=”{Binding
        RelativeSource={RelativeSource
          Mode=FindAncestor,
          AncestorType={x:Type Expander}},
        Path=ActualWidth}”

      />
  </Expander.Header>
  <TextBlock Background=”Red”>
    I am some content…
  </TextBlock>
</Expander>

NOTE: Be sure to read the original post to learn about the limitations of this XAML-only approach, and when it is necessary to use the original technique.


Writing unit tests for classes that use DispatcherTimer

July 14, 2007

I just published an article on CodeProject which discusses how to write unit tests for classes that depend on DispatcherTimer to get their work done.

It seemed like a pretty straightforward task when I first tried to write a unit test for functionality which uses DispatcherTimer.  Wow, was I wrong!  It was actually a mind-bending experience, which required me to learn a lot about how WPF’s Dispatcher and DispatcherTimer work.  If you want to read more about what I learned along the way, here’s the link: http://www.codeproject.com/KB/WPF/UnitTestDispatcherTimer.aspx


Extending the WPF Command system

July 12, 2007

There is a very interesting thread on the WPF Forum which discusses how to augment the Command system in WPF.  A fellow by the name of Patrick Klug explains how his team made use of the CommandParameter property of CanExecuteEventArgs to pass extra information about the status of a Command.  His post was followed up by Bill Henning, of Actipro Software, who explained how his company’s WPF control library extends the basic Command system to pass more information about a command than is possible by default.  I highly recommend checking it out.

Here’s the link: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1809894&SiteID=1

Thanks for sharing your interesting ideas, guys!


Follow

Get every new post delivered to your Inbox.

Join 287 other followers