Zen and the art of WPF

February 23, 2008

Once upon a time, there was a WPF application that had two types of users:

zen 1

The UI had two buttons. One button allowed anyone to view an account. The other button, though, was only for certain privileged people to click, because it deleted an account.

zen 2

When the program was first released, a careless developer introduced a subtle bug in the logic which determines if an account can be deleted.

zen 3

For 99% of the non-privileged users, it never dawned on them that it was possible to delete an account when they ran the program.

zen 4

One of the users had a grudge against the world, and also some knowledge of a little tool known as Snoop. He was determined to bring down The Man one account at a time.

zen 5

When this malicious user ran the app, he snooped around until he found the hidden Delete Account button.

zen 6

He found that button’s Visibility property and set it to ‘Visible’.

zen 7

Since the careless developer did not expect that button to ever be visible when the user is not allowed to see it, the button was not disabled and could be clicked.

zen 8

Tempting fate, the jaded user clicked the button.

zen 9

After much fire and brimstone fell from Corporate Skies, the once careless developer learned a valuable lesson. He understood that WPF element trees can be viewed and modified while the application is running. He sharpened his code-sword and prepared for battle.

zen 10

In one swift movement, he defeated his foe.

zen 11

After the new version of the application was deployed, the malicious user once again attempted his devious maneuver. However, this time, he found that after unearthing the Delete Account button in Snoop, the button was disabled.

zen 12

He could not click it. The button’s IsEnabled property could not even be set to true, since the Delete command’s CanExecute handler was forcing the button to be disabled. He could not use the application to continue his rampage against The Man. It broke his heart, and he cried.

zen 13

Download the application’s source code here (rename the file extension from .DOC to .ZIP).

Advertisements

Differences between Label and TextBlock

July 4, 2007

I always thought it was odd that WPF has both TextBlock and Label.  They both are responsible for displaying a small amount of text.  Every piece of documentation about Label I have read justifies its existence by mentioning that it allows for access keys (a.k.a. mnemonics).  Access keys allow you to hit Alt + SomeKey to quickly interact with a control in the UI, such as hitting Alt + O to click an “OK” button.  My thought has been, “Why not just add support for access keys to TextBlock and get rid of Label?”

Recently I discovered some reasons why it makes sense for Label to exist.  The rest of this blog post sheds some light on that obscure topic.  Throughout this blog post we will refer to a demo application which looks like this when you first run it:

Label vs TextBlock (initial UI)

The “Username:” text is a TextBlock and the “Password:” text is a Label.

TextBlock is not a control

Even though TextBlock lives in the System.Windows.Controls namespace, it is not a control.  It derives directly from FrameworkElement.  Label, on the other hand, derives from ContentControl.  This means that Label can:

  1. Be given a custom control template (via the Template property).
  2. Display data other than just a string (via the Content property).
  3. Apply a DataTemplate to its content (via the ContentTemplate property).
  4. Do whatever else a ContentControl can do that a FrameworkElement cannot.

Below is a fragment of the class inheritance hierarchy containing Label and TextBlock:

Label vs TextBlock (class hierarchy)

Label text is grayed out when disabled

When a Label’s IsEnabled property returns false its text is “grayed out.”  TextBlock does not have this behavior by default.  Here is what the demo app looks like when the input area is disabled.  Keep in mind that the “Username:” text is a TextBlock and the “Password:” text is a Label:

Label vs TextBlock (disabled)

The reason Label text turns gray when it is disabled is due to the fact that Label’s default control template has a Trigger which explicitly sets the Foreground property when IsEnabled is false.  Here is that Trigger from Label’s default control template:

Label vs TextBlock (Label’s trigger)

If we really wanted TextBlocks to appear grayed out when disabled, we could repurpose that XAML seen above into a Style which is applied to TextBlocks (as seen in the demo project available at the end of this post).

Label supports access keys

This is the standard explanation of why Label exists.  You can associate a Label with another control, such as a PasswordBox, and allow the user to type an access key defined by the Label to set focus to the other control.  The access key is represented in the UI by drawing a line under the appropriate character.  If the user presses the Alt key and then the designated “access character” the target control will be given focus.

Here is what the demo application looks like after the user presses the Alt key:

Label vs TextBlock (access key indicators)

Notice how every piece of text in the UI has an access key indicator, except for the “Username” TextBlock.  The “Password” Label and its target (a PasswordBox) were declared like this:

Label vs TextBlock (setting Label.Target)

Label is much heavier than TextBlock

So far we have examined why Label can be considered better than TextBlock, but now its time to discuss the benefits of using a TextBlock instead.  Label has a higher runtime overhead than TextBlock.  Not only does Label inherit from two classes further down the inheritance hierarchy than TextBlock, but its visual tree is much more involved.

I snooped the visual tree of the demo app to see what was really going on when you create a Label with an access key defined.  Below is a screenshot of Snoop displaying the visual trees of both the “Username” TextBlock and the “Password” Label (with an access key defined):

Label vs TextBlock (snooping the visual tree)

The “Username” TextBlock’s visual tree contains no child elements.  The Label, however, is much more involved.  It has a Border, which contains a ContentPresenter, which hosts an AccessText element, which finally uses a TextBlock to display the text.  So it turns out that using a Label is really just an elaborate and customizable way of using a TextBlock.

Links

Label Class

TextBlock Class

AccessText Class

ContentPresenter.RecognizesAccessKey Property

How to: Create a Control That Has an Access Key and Text Wrapping

Snoop (a WPF utility)

Download the demo

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


Tips on how to debug and learn about WPF

March 29, 2007

Debugging WPF applications can be a tough challenge, especially for people just starting off with the platform.  Not only is it tough to debug WPF code, but just figuring out how to build what you dream up can be a challenge.  The point of this blog post is to make it easier to find information about how to design WPF applications, and how to debug them efficiently.

Getting info and help


Use Google (duh).  I’m amazed at how many questions I see posted around the web asking how to do something in WPF, whose answer is immediately obvious after a simple Google search.Visit Microsoft’s WPF Forum and use the Search page.  You might be surprised at how many times your question has been asked and answered there.  Be sure to use the Advanced Search Options and filter on the WPF Forum:

Search the WPF Forum

If your searches come up empty, you should post your question on the WPF Forum.  There are many helpful people who monitor that forum.  However, before posting your first question there, be sure to read this post by Rob Relyea about forum etiquette.

The MSDN documentation is your friend.  If you want to have a really fast and helpful friend use your local copy of the help files, which was installed during installation of the Windows SDK.  If you don’t know what I’m referring to, go Start | All Programs | Microsoft Windows SDK | Windows SDK Documentation.

Read books about WPF.  I have found ‘WPF Unleashed’ and ‘Applications = Code + Markup’ to be great. 

Read peoples’ WPF blogs.  For a great listing of WPF blogs, check out Tim Sneaths’ WPF blog roll here.

Check out all of the great resources on http://wpf.netfx3.com/.  That site has a lot of samples, demos, links to reading material, etc.  It’s definitely a site to put in your Favorites list.

http://www.NetFxGuide.com is another gem.

CodeProject articles about WPF are, of course, a great resource.  You can view a list of all their WPF articles here.

Debugging tips and tricks


Inner Exceptions reveal the answer to so many runtime exceptions that it’s barbarically annoying (yet helpful).  I often see questions where folks ask why their WPF app is blowing up, and the answer lies in an InnerException one or two levels deep. In case you have no idea what I’m talking about, allow me to explain.  The standard .NET Exception class has a property called InnerException.  That property can reference another Exception, whose message might contain an explanation of why the error occurred.  The InnerException itself might have a reference to its own InnerException, and so on. 

As exceptions are thrown, handled, and re-thrown in the .NET Framework exceptions can be chained together to provide a “history” of the error.  Many WPF exceptions have several nested InnerExceptions, each of which might contain a useful piece of evidence you can use while debugging.  Usually the deepest (most nested) exception is the one which explains what the real problem is.When you are running an application in debug mode and an exception is thrown, you will first be confronted with Visual Studio’s exception dialog:

Open the exception dialog

After clicking the View Detail link, you can dig into the guts of the exception and check out what actually went wrong:

Viewing nested InnerExceptions

There is a fantastic free utility, by Pete Blois, called Snoop which you should download if you want to do any serious WPF debugging.  Snoop is the best WPF debugging tool out there so far.  Get it.  Not only will it show you the entire element tree of a WPF user interface, but it will let you see many other things such as: what routed events have been raised, data binding errors, a preview of any element, a zoomed view of an element, and more.

A while back Mike Hillberg blogged about the TraceSources built into WPF.  I’ve used this for debugging and educational purposes, and found it to be useful for both. As he mentions, the data binding source is “on” by default, as you can see when viewing the Output window in Visual Studio while debugging a WPF app.

As always, get Lutz Roeder’s Reflector.  That is the best .NET utility application of all time.  It will decompile any .NET assembly (including the WPF assemblies) and allow you to read how they work, in the high-level language of your choice.  If you don’t already have it, what’s wrong with you? 🙂  Also, there is a BAML-to-XAML converter add-in for Reflector you can use to inspect the resources a WPF assembly has embedded in it.

Create a dummy value converter and use it, often.  If you ever want to know what value a Binding is passing from one object to another, inject your dummy value converter into it and set a breakpoint.  I’ve used this little trick a million times and it never fails to help.  Here’s the basic gist:

Dummy ValueConverter

Another useful trick for debugging is to use the DependencyPropertyHelper’s GetValueSource static method.  It takes in a DependencyObject and a DependencyProperty, and returns a value indicating what actually set that property (with regards to the rules of precedence associated with DPs).

If you have any other useful tips that belong in this blog post, feel free to leave me a comment with your ideas.


Stretching Content in an Expander Header

February 24, 2007

[EDIT]

Long after this post was written, a fellow by the name of Patrick Jones left a comment which showed another way to implement the functionality shown in this post.  Upon reading his clever implementation, I realized that this is entirely possible to achieve without writing a single line of code.  The trick relies on binding the Expander’s header element’s Width to the ActualWidth of the Expander.  Here’s a demo:

<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: This technique makes the header element wider than the available space (it does not subtract out the width of the Expander’s expansion indicator).  If your header element has a border around it, such as a Button, this XAML-only technique will not work properly because the header element is clipped on the righthand side.  If you need the header element to be exactly the right width, then you will need to use the approach explained below.

[/EDIT]

Someone recently asked me how to stretch the content of an Expander’s header.  By default the Expander will force the header’s content to “auto-size” itself, like this:

Default Expander header (unstretched)

In the screenshot above, a DataTemplate was applied to the Expander’s HeaderTemplate property.  That template consists of a Border with a blue background wrapping a ContentPresenter.  Notice that the Border does not extend all the way to the right edge of the header area.  The desired effect is to have the header content stretch, like this:

Stretched Expander header content

I first tried to make the header content stretch by setting properties on the Border in the DataTemplate.  No matter which properties I set it had no effect, so I realized that a little Snooping was necessary to get to the bottom of this.  I fired up Snoop and soon realized why I could not stretch the header content.  The ContentPresenter which hosts the expanded HeaderTemplate elements (note, ‘expanded’ in the sense of ‘instantiated’) has its HorizontalAlignment explicitly set to ‘Left’.  D’oh! 

Here’s what I’m referring to, when using the Expander’s default HeaderTemplate:

Snooping around in the default Expander visuals
(click me)

The question now is: how can we set that ContentPresenter’s HorizontalAlignment to ‘Stretch’?

I know of two good ways to go about setting that property.  We could get a copy of Expander’s default control template (for each OS theme…), find the ContentPresenter in the template, set the HorizontalAlignment to ‘Stretch’, and then use that modified control template in our application.  For you XAML-only zealots out there, that’s the way to go.

Alternatively, if you are not restricted by a XAML-only rule, you can perform a little kung fu in the code-behind to make it happen.  Here’s the magic:
How to stretch the content of the Expander’s header
(click me)

You can download the demo project here.  Change the file extension from .DOC to .ZIP and then decompress it.