Redoing the Options Dialog in BabySmash

Scott Hanselman introduced us to BabySmash today. It’s an app for his kids that he developed using his arcane Win32 knowledge in a WPF app. He did it on purpose, mind you, to teach himself WPF, with us watching.

I think this is a fantastic idea. When I was writing the AutoComplete TextBox series, I thought it would be a cool idea for all the major WPF book authors (Adam Nathan, Chris Sells & Ian Griffiths, Charles Petzold and Chris Anderson) to write their implementations of the same problem. They’re all very good at explaining, they’d all come up with different solutions and we could all figure out the best way to do things in WPF, as Scott alludes to in his post on BabySmash.

I’ve taken a look at the code and, boy, it needs work. I saw immediately something I’ve experienced pain with before, which I’ll talk about in this post: custom settings. In .NET 2.0, one of the cool The default Settings.settings file.unsung heroes is the settings code in System.Configuration. Note that it’s not tied to WPF or WinForms. With it, you’re able to have user- or app-scoped settings. They can be local or roamable. The framework takes care of storage, although it’s extensible. Visual Studio assists with code-gen so you can access your settings with code.

By default, VS will create a Settings class that inherits from ApplicationSettingsBase in the YourProjectNamespace.Properties namespace. The settings you create in the Settings designer get properties generated for them. The Settings class also has a static instance accessed through the Default property. Scott actually created this file, but then didn’t use it. I haven’t used ClickOnce, but I just can’t see Microsoft not supporting the settings file automagically in ClickOnce.

Pictured below is BabySmash’s settings with Scott’s intended properties filled in.

The settings Scott already used in BabySmash filled in the settings file

So, like I said, this is independent of UI framework. How do we use it in WPF? Databinding! By far the best thing of WPF, even though you have to put some time in to learn it.

Before I show the code to databind to the application settings, allow me to show you the XAML for the Options page in BabySmash.

<Window x:Class="BabySmash.Options"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Baby Smash! - Options" Unloaded="Window_Unloaded" Loaded="Window_Loaded" Height="188" Width="268" ShowInTaskbar="False" Topmost="True" WindowStartupLocation="CenterScreen" WindowStyle="ThreeDBorderWindow" ResizeMode="NoResize">
    <Grid>
        <Button Height="23" Name="OK" VerticalAlignment="Bottom" Click="OK_Click" IsDefault="True" Margin="64,0,102,9">OK</Button>
        <Button Height="23" Margin="0,0,8,9" Name="Cancel" VerticalAlignment="Bottom" IsCancel="True" HorizontalAlignment="Right" Width="80" Click="Cancel_Click">Cancel</Button>
        <Label Height="28" Margin="14,19,0,0" Name="lblClearAfter" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120">Clear After x Shapes</Label>
        <TextBox Height="23" Margin="0,19,8,0" Name="txtClearAfter" VerticalAlignment="Top" HorizontalAlignment="Right" Width="101"></TextBox>
        <CheckBox Margin="0,81,0,0" Name="chkForceUppercase" Height="16" HorizontalAlignment="Right" VerticalAlignment="Top" Width="109" >Force Uppercase</CheckBox>
        <ComboBox Margin="0,48,8,0" Name="cmbSound" Height="23" HorizontalAlignment="Right" VerticalAlignment="Top" Width="101" IsDropDownOpen="False">
            <ComboBoxItem>None</ComboBoxItem>
            <ComboBoxItem>Speech</ComboBoxItem>
            <ComboBoxItem>Laughter</ComboBoxItem>
        </ComboBox>
        <Label Height="28" Margin="14,43,112,0" Name="label1" VerticalAlignment="Top">Sounds</Label>
    </Grid>
</Window>

If you know XAML and how the WPF grid works, then you know that this is really bad code. This is probably the most egregious thing about WPF, IMO: the visual designer. Scott didn’t write this code. Visual Studio did.

Petzold has a great transcript/paper of a talk he gave to a New York user group in 2005 titled, Does Visual Studio Rot the Mind? In it he talks about the evolution of visual programming and Visual Studio. It’s written in 2005, before WPF even got its name, but while he was writing his book, Applications = Code + Markup. But the points he raises are still valid. WPF is, by default, laid out without reference to pixels. The intention of its designers was that with WPF, you say what you want, the WPF figures out how to make it so. Most of the new frameworks from Microsoft have that in their design: "tell me what, I’ll figure out how."

In WPF’s case, it’s completely undermined by the visual designer in Visual Studio. Note above the code snippet from Scott’s Options page: see all those Margin attributes? That’s like hard-coding the same string value in more than one place. This is a dialog box, but humour me. Suppose we allowed this dialog to be resized by the user. What would happen? Chaos.

 The visual chaos of visual studio defaults.

This is what Visual Studio gives you out of the box. Shameful. And if you want to use databinding, forget it, you have to write the XAML by hand. I am dimly aware of Expression Blend; I’ve used it a few times and I think I remember it being a little smarter than Visual Studio. I think that shows how Microsoft is a little out of touch with developers outside of Microsoft. In theory, I like the idea that developers can work on the app doing something, while designers work on the app’s appearance. Really good idea, in theory. In my experience, the developer is the designer the majority of the time. In this scenario, Visual Studio needs a lot more work.

Anyway, let’s stop ranting. I also think it’s a developer’s responsibility to learn either how technology is used if it’s well-established, in the case, of, say, PHP or ASP.NET; or how its designers intended it to be used in the case of WPF. That’s what I’ve done, and what I’m still doing now. So let’s make an Options window that binds to the app settings. Scott’s was laid out, as he intended it, as the following:

The BabySmash Options dialog

There are plenty of ways to do this with the default panel types in WPF. I’ll use the Grid since it’s the most powerful, the default choice and hence the most popular. I’ll preserve as much of what Scott had, and try to make it pixel perfect.

OK, I’m back. Did you miss me? Here’s what I have:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1.Properties"
        xmlns:l="clr-namespace:WpfApplication1"
        Title="Baby Smash! - Options" 
        Height="188" Width="268"
        ShowInTaskbar="False" 
        Topmost="True" 
        WindowStartupLocation="CenterScreen" 
        WindowStyle="ThreeDBorderWindow" 
        ResizeMode="NoResize">
    <Window.Resources>
        <local:Settings x:Key="settings" />
    </Window.Resources>
    <Grid DataContext="{StaticResource settings}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Label Height="23" Margin="10,20,0,0" Grid.ColumnSpan="2">Clear after x Shape</Label>
        <TextBox Text="{Binding Path=Default.ClearAfter}" 
                 Height="23"  Grid.Column="1"
                 Margin="15,20,0,0"/>
        <Label Height="23" Grid.Row="1" Margin="10">Sounds</Label>
        <ComboBox Grid.Column="1" Grid.Row="1" Height="23" Margin="15,0,0,0">
            <ComboBoxItem >None</ComboBoxItem>
            <ComboBoxItem >Laughter</ComboBoxItem>
            <ComboBoxItem >Speech</ComboBoxItem>
        </ComboBox>
        <CheckBox Grid.Row="2" Grid.Column="1" Margin="15,0,0,0"
                  IsChecked="{Binding Path=Default.ForceUppercase,Mode=TwoWay}" >
            Force Uppercase
        </CheckBox>
        <StackPanel Orientation="Horizontal" Grid.Row="3" Grid.ColumnSpan="2" 
                    HorizontalAlignment="Right">
            <Button Name="okButton" IsDefault="True" 
                    Margin="0,7,10,7" 
                    Padding="30,0,30,0" Click="okButton_Click">OK</Button>
            <Button IsCancel="True" 
                    Margin="5,7,7,7" 
                    Padding="15,0,15,0">Cancel</Button>
        </StackPanel>
    </Grid>
</Window>

It looks more verbose for sure, but I think that’s more because of editing by hand and using the ENTER key. Let’s pull out unnecessary stuff and show the code that binds to the application settings

<Window x:Class="WpfApplication1.Window1"
        xmlns:local="clr-namespace:WpfApplication1.Properties"
        xmlns:l="clr-namespace:WpfApplication1"
        >
    <Window.Resources>
        <local:Settings x:Key="settings" />
    </Window.Resources>
    <Grid DataContext="{StaticResource settings}">        
        <TextBox Text="{Binding Path=Default.ClearAfter}" />
        <CheckBox IsChecked="{Binding Path=Default.ForceUppercase}" >
            Force Uppercase
        </CheckBox>
        <StackPanel >
            <Button Name="okButton" IsDefault="True" 
                    Margin="0,7,10,7" 
                    Padding="30,0,30,0" Click="okButton_Click">OK</Button>
            ...
        </StackPanel>
    </Grid>
</Window>

There are some concepts you’ll see over and over again WPF: the use of ResourceDictionaries (Window.Resources in the XAML), DataContext, and DataBindings. I won’t explain all of it in detail (this post is long as is), but I’ll briefly explain it and bold terms that you can search the internets for more info.

Most of the XAML should be familiar even if you’ve never seen it before. It’s fairly close to ASP.NET code, if memory serves, and the XML hierarchy is a good fit for a model that represents a window as a nested tree of controls. The Windows.Resources element adds a Settings object to the window’s ResourceDictionary. All resource dictionary items must have a key to refer to. We set the DataContext on the Grid to the settings object declared in the resources. It’s a StaticResource which means that WPF loads it once and stops listening to updates to that resource. The DataContext is essentially associating the Settings object with the Grid. The  Binding on the TextBox’s Text property is BindingExpression whose Path points to the Default.ClearAfter property of the Settings object. That’s a little advanced, but hey, it’s "real world." And that’s all you have to do to get the settings to show up in the right controls. Notice there is no procedural code.

There’s one more thing to talk about before I quit. The Settings object’s properties change when you change the values in the controls (set the TextBox to 32, and ClearAfter is set to 32), but we have to tell the Settings object that we want to keep those values. We do that in okButton’s handler:

private void okButton_Click(object sender, RoutedEventArgs e)
{
   Properties.Settings.Default.Save();
   this.Close();
}

Too easy, eh?

There are some caveats because I didn’t test thoroughly: databinding by default updates the source after focus changes so if you set the TextBox to 32, then click OK, it may not update the property properly as you’d expect. I explicitly left the third property in settings to be set by you if you want to take up the challenge. I added the settings in BabySmash but they weren’t showing up properly. I don’t know why and I didn’t pursue.

So there you have it. I didn’t show Scott’s Option dialog code, but I’ve significantly reduced it. My Options Dialog window XAML code may be a little longer but I get some layout benefits by using the Grid to its potential. Of course, you may do something different, and it may be better, but that’s the whole point of the Scott’s app. There are some treats in the solution below. I got tired of writing this post before I covered everything that I noticed. I’m going to play video games now.

The Missing .NET #4: Cue Banner in WPF (I mean, Watermark in WPF)

The .NET framework is huge, but not so huge that it does everything for everyone; there are things that they in Redmond miss or don’t do for whatever reason but is still generally applicable to many developers. So, dear reader, I present to you a series of posts on stuff I find missing in .NET, typically where even the Google fails to find the answer. It could be a useful class, a technique, a good practice or documentation that should be in the framework but isn’t.


A regular reader would know I’m quite enamoured with the Cue Banner as UI tool. Once again, in WPF, Microsoft missed something fairly obvious for inclusion; and really easy to implement, as we’ll see. We’ve been through 2 revs of WPF since its release, and the number of new controls or new features on old controls is disappointing. In case you missed it, .NET 3.5 SP1 Beta was released a few weeks ago. The grand total of new controls in WPF? One; admittedly, a useful one – a WebBrowser control.

When I showed how to use the Cue Banner in Windows Forms, I mentioned that the Cue Banner is no app saver. It’s no laser show, fireworks or smoke machine. But it does add significantly to the usability of the app. Since we’re seeing it more frequently on the web now as well, I’d say the effectiveness of the Cue Banner is obvious.  When I mention usability, I mean the ease with which a human can use a tool, like software, not "it looks cool." I notice that people often confuse usability with prettiness in the software realm. But you’re smarter than that aren’t you, dear reader?

There are already two implementations of Cue Banners that I’ve seen in WPF, both have some cool features, but both inherit from TextBox which I find so limiting that I can’t really recommend them. The coolest one is the InfoTextBox in Kevin Moore‘s WPF Bag-O-Tricks which has been around since before WPF got its horrible name. The InfoTextBox is actually a great example of extending a Control in WPF. There is almost no code, except for the declared Cue Banner property, called, rather yuckily, TextBoxInfo. It truly shines in the overriding style (in generic\InfoTextBox.generic.xaml). It’s a collection of triggers and ControlTemplate; I still don’t understand how it’s working completely. If you want to see some WPF code written by someone who knows what they are doing, you should download the source and have a look. Anyway, the cool thing about the InfoTextBox is the effect Kevin created when you focus on the TextBox, but before you enter some text. You have to see it to believe it, so go download it!

The second implementation is not from WPF but from its younger, more attractive sibling, Silverlight 2. Poor WPF will probably be the Charlie to Silverlight’s Eddie Murphy, because of the Web’s ubiquity and importance. Silverlight 2 is still in beta, but it has had in its controls collection since the start, the unfortunately named WatermarkedTextBox.

My first Computer Science class was a mandatory class for my first degree in Physics. I’m not going to lie to you: I didn’t like it. Why I didn’t like it is for another blog post and it’s not why I brought it up. I have on occasion gone back to the code I wrote for my assignments and saw with amusement that all my variables were called x. Amusing, because I’m quite adamant on properly naming the classes, components, methods, variables, parameters in my code now, and have been since I started liking this whole computer thing. It’s too important for clarity. I’ve gone through the SomethingManager naming scheme phase, I pay attention to what FxCop says about naming when I create new classes and none of my variables are now named x. I’m fairly literate, so I know the meaning of the words that I use. The WPF team, on the other hand, doesn’t.

If Wikipedia is any authority, then a watermark, either digital, or …real, is for  permanently marking something with a mark to distinguish where the somethingIndiana Jones wants a little hint about your email textbox. came from. That little logo on the bottom corners of TV shows now? The ones that wreck plasma TVs because they never go away? Those are watermarks. They are always there. The whole point of a cue banner, on the other hand, is to provide just a little hint of what should go there. Once text is entered, then it goes away.

Here’s a couple more reasons WatermarkedTextBox sucks: Google knows about cue banners. It also knows about watermarks, but the real watermarks. The Silverlight controls has both a WatermarkedTextBox and TextBox. Um, why? Just make Watermark a property on TextBox. If it’s null, it doesn’t show up.

The cool thing about WatermarkedTextBox? Actually, cool is the wrong word for it but I hadn’t thought of it until seeing the WatermarkedTextBox demo page: using images or text as the cue banner. I extrapolated: why not anything as the cue banner?

Then I answered my own question.

Cue banners are useful on ComboBoxes and TextBoxes, so that eliminates the possibility of inheritance if I want to maintain this code and keep my sanity (ComboBox and TextBox don’t share enough code in WPF, namely, their Text properties are different). What else could I use? I know! Attached properties! I love those things.

The code for declaring attached properties, like all dependency properties, is pretty much all boilerplate:

public static class CueBannerService
{
  //there is absolutely no way to write this statement out
  //to look pretty
  public static readonly DependencyProperty CueBannerProperty = DependencyProperty.RegisterAttached(
                                "CueBanner", 
                                typeof (object), typeof (CueBannerService), 
                                new FrameworkPropertyMetadata(null, CueBannerPropertyChanged));

  public static object GetCueBanner(Control control)
  {
     return control.GetValue(CueBannerProperty);
  }

  public static void SetCueBanner(Control control, object value)
  {
     control.SetValue(CueBannerProperty, value);
  }

  private static void CueBannerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
    ...     
  }
}

This code declares CueBanner as DependencyProperty of type object, owned by the CueBannerService, and whose default value is null. The Get/Set methods are there by convention for the programmer who likes to declare stuff in code, and for the XAML engine to set things at design time. You can’t leave it out, even though it won’t be called at runtime if you set these properties in XAML. This is all standard stuff; the difference between this attached property and the rest, other than the name, is what happens in the PropertyChanged event handler. For a good intro to Dependency Properties, you check out Drew Marsh’s Introduction to DependencyProperties post.

She needs a tiny hint about your herbal remedy It’s Cue Banner’s nature to be set once. The Cue Banner’s only purpose is to provide a small hint to the user about the control with which it’s associated. So the property changed handler assumes that the value is only going to be set once. However, the control may show the cue banner multiple times during the lifetime of the app. We’ll start simply here and implement it only for TextBox and ComboBox. The behaviour of the Cue Banner for these two controls is to show itself if the Text value of the control is the default value (the empty string for these two controls) and to remove itself if the user focuses on the control. In my property changed handler, I basically want to get a reference to the control instance and listen for some of its events:

private static void CueBannerPropertyChanged(DependencyObject d, 
                                             DependencyPropertyChangedEventArgs e)
{
 Control control = (Control)d;
 control.Loaded += control_Loaded;
 if (d is ComboBox || d is TextBox)
 {
    control.GotFocus += control_GotFocus;
    control.LostFocus += control_Loaded;
 } 
}

There’s more coming in this method, hence the type check. My first implementation of this, when I just limited it to TextBox, was to set the TextProperty if the TextProperty was the empty string. Once the user focused on the control, I’d check to see if the TextProperty value was the CueBanner value, then set the TextProperty back to the empty string. This had the undesirable side effect of raising the TextChanged event on the TextBox. Since I can’t control when that gets raised, any handler that is listening to that event would have to check the cue banner value as well as the empty value. That’s not pretty at all. For most of the low-level input events there is a PreviewXxxChanged event that can be used to cancel the XxxChanged event, but TextChanged doesn’t have one.

So I needed another way. I could have tweaked styles like I did with the AutoComplete WPF implementation, but it didn’t really seem appropriate. Plus, it’s a proven method that I’ve already found; that’s just downright boring. The whole point of implementing these things is to learn different aspects of WPF. Basically what I needed was a way to display something on the screen in the same spot as the TextBox, but I couldn’t use the Text property for fear of messing with the developer’s expectations of an unobtrusive, useful addition to WPF.

It usually happens that when I’m trying to solve a problem where the solution isn’t obvious, the solution comes all at once and at the oddest moment. In this case, it came when I was bombing around Beatriz Costa’s excellent WPF blog, reading this post on Drag and Drop, after reading Chris Sells and Ian Griffiths’ WPF book, Programming WPF, Chapter 18 to be precise. If you don’t own that book – well, you should – Chapter 18 deals with custom controls. After reading those two articles, I had enough stuff bouncing around in my brain to come up with the answer to my problem: the adorner layer.

I have no doubt that you’ve seen the adorner layer in action: the underwhelming WPF visual designer in Visual Studio uses it to show the size values changing as you resize your window or control. The adorner layer, though, is always around, and sits atop the window of your app; think of it as a sheet of glass. Drag and drop is a good use for it as well: since you’re moving all over the visual tree, implementing drag and drop any other way would cause you to go insane.

For my needs, the AdornerLayer is perfect. A small visual cue above the control (above as in higher in the z-order) that goes away when needed. The AdornerLayer contains adorners, so that’s the next thing I have to write. An Adorner is a UIElement so it has all the power of WPF behind it; I want to take advantage of it. My CueBanner will likely be a string, but it could be something else, an image, say. I want something that will handle all that for me. Using the It’s in the Framework, Dummy principle, I knew that the good folks on the WPF team already came up something that does that, the ContentPresenter. That’s all my CueBannerAdorner does: wrap a ContentPresenter in an Adorner. It’s a blatant, purposeful copy of Bea Costa’s DraggedAdorner from the Drag and Drop sample.

internal class CueBannerAdorner : Adorner
{
   private readonly ContentPresenter contentPresenter;

   public CueBannerAdorner(UIElement adornedElement, object cueBanner) : 
      base(adornedElement)
   {
      this.IsHitTestVisible = false;

      contentPresenter = new ContentPresenter();
      contentPresenter.Content = cueBanner;
      contentPresenter.Opacity = 0.7;
      contentPresenter.Margin =
         new Thickness(Control.Margin.Left + Control.Padding.Left, 
                       Control.Margin.Top + Control.Padding.Top, 0, 0);
   }

   private Control Control
   {
      get { return (Control) this.AdornedElement; }
   }

   protected override Visual GetVisualChild(int index)
   {
      return contentPresenter;
   }

   protected override int VisualChildrenCount
   {
      get { return 1; }
   }

   protected override Size MeasureOverride(Size constraint)
   {
      //here's the secret to getting the adorner
      //to cover the whole control
      contentPresenter.Measure(Control.RenderSize);
      return Control.RenderSize;
   }

   protected override Size ArrangeOverride(Size finalSize)
   {
      contentPresenter.Arrange(new Rect(finalSize));
      return finalSize;
   }
}

By default, WPF sizes everything to the content it creates. The one thing that took me a little time to figure out is the right Size value to pass to the ContentPresenter in MeasureOverride. Amazing how generic that code is, eh? Despite all my griping earlier, WPF is still totally awesome. Classes like ContentPresenter are pure magic.

Great. Now we just need to add our adorner to the AdornerLayer. We do that in the event handlers I subscribed to in the CueBannerPropertyChanged handler:

private static void control_GotFocus(object sender, RoutedEventArgs e)
{
   Control c = (Control)sender;
   if (ShouldShowCueBanner(c))
   {
      RemoveCueBanner(c);
   }
}

private static void control_Loaded(object sender, RoutedEventArgs e)
{
   Control control = (Control)sender;
   if (ShouldShowCueBanner(control))
   {
      ShowCueBanner(control);
   }
}

private static void RemoveCueBanner(UIElement control)
{
   AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);

   Adorner[] adorners = layer.GetAdorners(control);
   if (adorners == null) return;
   foreach (Adorner adorner in adorners)
   {
      if (adorner is CueBannerAdorner)
      {
         adorner.Visibility = Visibility.Hidden;
         layer.Remove(adorner);
      }
   }
}

private static void ShowCueBanner(Control control)
{
   AdornerLayer layer = AdornerLayer.GetAdornerLayer(control);
   layer.Add(new CueBannerAdorner(control, GetCueBanner(control)));
}

private static bool ShouldShowCueBanner(Control c)
{
   DependencyProperty dp = GetDependencyProperty(c);
   if (dp == null) return true;
   return c.GetValue(dp).Equals("");
}

private static DependencyProperty GetDependencyProperty (Control control)
{
   if (control is ComboBox)
      return ComboBox.TextProperty;
   if (control is TextBoxBase)
      return TextBox.TextProperty;
   return null;
}

That just about does it. Now you can set a cue banner to just about anything for TextBox or ComboBox. The code is similar to how ToolTip works. Here are a few examples:

<StackPanel>
    <TextBox Name="textBox1" 
         VerticalAlignment="Top" 
         HorizontalAlignment="Stretch">
        <sm:CueBannerService.CueBanner>
            <Image Source="Forest.jpg"/>
        </sm:CueBannerService.CueBanner>
    </TextBox>
    <ComboBox Height="23" 
              sm:CueBannerService.CueBanner="Pick Something" 
              IsEditable="True" 
              IsDropDownOpen="False">
        <System:String>Geek</System:String>
        <System:String>Cool Guy</System:String>
    </ComboBox>

</StackPanel>

But I’m not done yet! Condy's not getting enough hints.

Why limit ourselves to just text controls? I know I keep reminding you about what a cue banner is, but here it is again: a small visual hint about what you’re supposed to do. That needn’t be limited to edit controls.

I recently started looking into this whole Web 2.0 thing and got a Flickr account. Their Uploadr tool is pretty useful and look what they have in their image list pane thing (it’s written with XUL on Mozilla):

Flickr's Uploadr tool

Here’s where all that generic code shines. We can easily add some support for CueBanners on List controls, we just need some way to tell when to display it and when to turn it off. In WPF, when we talk about List Controls, we’re talking about ItemsControl. There is a slight wrinkle in that there are two ways to add Items to an ItemsControl: through the non-dependency property, Items, or through the ItemsSource dependency property using data binding. When we first get a reference to our ItemsControl, we have to account for both:

   1: private static void CueBannerPropertyChanged(DependencyObject d, 
   2:                                              DependencyPropertyChangedEventArgs e)
   3: {
   4:  Control control = (Control)d;
   5:  control.Loaded += control_Loaded;
   6:  if (d is ComboBox || d is TextBox)
   7:  {
   8:     control.GotFocus += control_GotFocus;
   9:     control.LostFocus += control_Loaded;
  10:  }
  11:  if (d is ItemsControl && !(d is ComboBox))
  12:  {
  13:     ItemsControl i = (ItemsControl) d;
  14:     //for Items property
  15:     i.ItemContainerGenerator.ItemsChanged += ItemsChanged;
  16:     itemsControls.Add(i.ItemContainerGenerator, i);
  17:     //for ItemsSource property
  18:     DependencyPropertyDescriptor prop =
  19:        DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, i.GetType());
  20:     prop.AddValueChanged(i, ItemsSourceChanged);
  21:  }
  22: }

Here’s the complete implementation of CueBannerPropertyChanged. I’m not entirely happy with this implementation, but I couldn’t see a way to handle the Items otherwise. The Items collection isn’t a dependency property so we have to use something else. What I really want is for the ItemsControl to raise an event when the Items collection changes. I had to settle for going through the ItemsControl’s ItemContainerGenerator (the class factory for ItemContainers), which meant I had to track ItemContainerGenerators to ItemsControls because I can’t access the ItemsControl from the ItemContainerGenerator’s ItemsChanged event handler, hence the itemsControls dictionary on line 16. If anyone knows a better way, please leave a comment (if you got down this far :)). The ItemsSource property is a dependency property so we can use the DependencyPropertyDescriptor class to add an EventHandler when the property value changes. I was worried about the sender in that event but it turns out to be what you’d expect it to be, namely the ItemsControl instance. Now you can easily add a CueBanner to a ListBox

<Window x:Class="WpfApplication1.Window3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sm="clr-namespace:Soundmind.Windows;assembly=Soundmind.Windows"
    Title="Window3" Height="300" Width="300">
    <Grid>
        <ListBox >
            <sm:CueBannerService.CueBanner>
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <TextBlock Height="23">
                        <Run Text="Drag some images here, bitches" FontSize="18"/>                        
                    </TextBlock>
                    <TextBlock TextAlignment="Center">
                        <Run Text="Or click add to find photos" FontFamily="Arial" />
                    </TextBlock>
                </StackPanel>
            </sm:CueBannerService.CueBanner>
        </ListBox>
    </Grid>
</Window>

which looks like the following:

A ListBox with a CueBanner

The Missing .NET #3: An AutoComplete TextBox in WPF, Part 4 – WPF Flourishes

The .NET framework is huge, but not so huge that it does everything for everyone; there are things that they in Redmond miss or don’t do for whatever reason but is still generally applicable to many developers. So, dear reader, I present to you a new series of posts on stuff I find missing in .NET, typically where even the Google fails to find the answer. It could be a useful class, a technique, a good practice or documentation that should be in the framework but isn’t.


Well, we’re getting close. Part 1 showed that the standard controls in WPF were all you needed to make autocomplete happen. Part 2 started us on the road to packaging it up into a reusable component; Part 3 went neck deep into advanced WPF territory to finish the hard part of our implementation. In this final segment, I’ll cover some neat features of WPF that we can take advantage of to make our AutoComplete TextBox even better.

There is one more thing to discuss: improvements over the Win32 implementation. The code has a little more in it than what I’ve shown. When creating this, I based it on the ComboBox in the Windows Run dialog. What’s the point of doing this in WPF if we don’t take advantage of the new platform? I touched on Templates earlier when I replaced the TextBox template with my own in Part 3. The ListBox (more accurately, the ItemsControl) allows us to template the UI for our data objects with DataTemplates. What if we exposed that so we could change the look of the autocomplete list? Say we wanted to add an image for each item, as well as text.

Also, what if I wanted to index on more than one property? Currently, my implementation works on the ToString() method for each object, keeping the instances in the list that correspond to what’s typed in the TextBox. Wouldn’t it be cool if we could arbitrarily choose the properties to index on? Then we could get the same behaviour as the Outlook addressee textboxes in the New Mail Window.

I’ll deal with first one, um, first, since it’s the easiest: just expose a DependencyProperty or another Attached property of type DataTemplate. In the PropertyChanged event handler, assign it to the ListBox.ItemTemplate property which you can see in the code.

The second is just a matter of adding a new Dependency Property and changing the CollectionViewSource.Filter event handler like so:

private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
   AutoCompleteFilterPathCollection filterPaths = GetAutoCompleteFilterProperty();
   if (filterPaths != null)
   {
      Type t = e.Item.GetType();
      foreach (string autoCompleteProperty in filterPaths)
      {
         PropertyInfo info = t.GetProperty(autoCompleteProperty);
         object value = info.GetValue(e.Item, null);
         if (TextBoxStartsWith(value))
         {
            e.Accepted = true;
            return;
         }
      }
      e.Accepted = false;
   }
   else
   {
      e.Accepted = TextBoxStartsWith(e.Item);
   }
}

where AutoCompleteFilterPathCollection is a custom Collection<string> class with a TypeConverter applied so that we can write the list of properties in a property attribute as a comma-separated list in XAML thusly:

<TextBox ac:AutoComplete.FilterPath="LastName,Email"
         ac:AutoComplete.Source="{Binding Source={StaticResource people}}" 
         Name="textBox2"></TextBox>

Then we can get an autocomplete textbox that behaves similar to the Outlook To address bar, that indexes on Name and Email. Easy.

API Design Aside: Now we have three Dependency Properties; the client XAML is looking a little cluttered. At this point I may want to make my own AutoComplete object and have one attached DependencyProperty of that type that you set on the TextBox. This has the advantage of enabling sharing AutoComplete data across many controls. But, on the other hand, that design sacrifices the ease of use. There are a couple of ways to present this to the developer, now, is my point. I’ll leave that as an exercise for the reader.

The final thing I wanted to do was show how simple it is to enable this to work on ComboBoxes. It requires just a quick refactoring to parameterize a few things when we set the control in the AutoComplete instance, as shown in Part 3, which I reproduce here:

private static void OnSourcePropertyChanged(DependencyObject d, 
                                    DependencyPropertyChangedEventArgs e)
{
   AutoComplete ac = new AutoComplete();
   ac.TextBox = (Control)d;
   ac.ViewSource.Source = e.NewValue;
   d.SetValue(AutoCompleteInstancePropertyKey, ac);
}

internal Control TextBox
 {
    set 
    {
       control = value;
       Style s = (Style)this["autoCompleteTextBoxStyle"];
       viewSource = (CollectionViewSource)control.GetViewSource(s);
       viewSource.Filter += CollectionViewSource_Filter;
       value.SetValue(Control.StyleProperty, this["autoCompleteTextBoxStyle"]);
       value.ApplyTemplate();
       autoCompletePopup = (Popup) value.Template.FindName("autoCompletePopup", value);
       value.AddHandler(System.Windows.Controls.TextBox.TextChangedEvent, 
                                new TextChangedEventHandler(textBox1_TextChanged));
       value.LostFocus += textBox1_LostFocus;
       value.PreviewKeyUp += textBox1_PreviewKeyUp;
    }
 }

As you see, I’ve typed the TextBox property to Control so I can set this to a ComboBox as well, but there are a few things we’ll have to move into a custom type. For starters, the Style for ComboBox is different than TextBox, so we’ll have to repeat the steps that we took when extracting the TextBox style, namely (deep breath) open XamlPadX, extract the ComboBox style, put it in my ResourceDictionary, add the ListBox control to the visual tree and add the CollectionViewSource to the Style’s Resources.

Once we’ve done that, we want to change the TextBox property above. The two things that we need to change are the hard-coded resource key, "autoCompleteTextBoxStyle"; and we have to parameterize where the CollectionViewSource comes from which you can tell from the two Styles. You can see the code for all the details, but the TextBox property (which I should rename) now looks like this:

internal Control TextBox
{
   set 
   {
      control = AutoCompleteControl.Create(value);
      Style s = (Style)this[control.StyleKey];
      viewSource = control.GetViewSource(s);
      viewSource.Filter += CollectionViewSource_Filter;
      value.SetValue(Control.StyleProperty, this[control.StyleKey]);
      value.ApplyTemplate();
      autoCompletePopup = (Popup) value.Template.FindName("autoCompletePopup", value);
      value.AddHandler(System.Windows.Controls.TextBox.TextChangedEvent, 
                                    new TextChangedEventHandler(textBox1_TextChanged));
      value.LostFocus += textBox1_LostFocus;
      value.PreviewKeyUp += textBox1_PreviewKeyUp;
   }
}

My parameterization class is slightly more complicated because of other methods in the AutoComplete class. One thing that is truly magic in this case is setting the TextChangedEvent handler on the ComboBox. Notice that I’m adding a handler to the TextBox.TextChangedEvent. Look at the ComboBox API, and you won’t see a TextChangedEvent! Yet it works just as you’d expect it to. That’s some magic that I don’t understand. Magic or no, the ease with which we’ve introduced autocomplete for ComboBox can’t go unnoticed. Note also that the ComboBox’s own Items are unaffected by autocomplete (you can set them both to the same data source, though).

Phew! As you’ve seen over this massive edition of the Missing .NET, creating behaviour in WPF needn’t involve custom controls, but it does require a solid understanding of the underlying design concepts of WPF. There is definitely more we can do with this AutoComplete stuff as well. Hopefully, I’ve shown you the start of what’s possible.

The Missing .NET #3: An AutoComplete TextBox in WPF, Part 3 – Control Templates

The .NET framework is huge, but not so huge that it does everything for everyone; there are things that they in Redmond miss or don’t do for whatever reason but is still generally applicable to many developers. So, dear reader, I present to you a new series of posts on stuff I find missing in .NET, typically where even the Google fails to find the answer. It could be a useful class, a technique, a good practice or documentation that should be in the framework but isn’t.


In Part 1, I roughed in my AutoComplete Textbox with standard WPF controls. In Part 2, I decided to deploy this as an attached property but ran into some trouble with inserting my WPF controls into an control’s visual tree. In this part below, I show how I solved the visual tree problem using ControlTemplates.

Charles Petzold has an example of creating a ControlTemplate in code in his Applications = Code + Markup: A Guide to the Microsoft Windows Presentation Foundation (Pro – Developer). It involves creating a nested set of factories: truly painful. So I quickly abandoned it as a tenable method for replacing the ControlTemplate. That meant a XAML solution for writing out the ControlTemplate.

But a XAML solution creates its own problems, especially since I’ll have to access the objects created by the template in code (the CollectionViewSource for one, and another control that has yet to make its appearance in this saga). Again, my ignorance with these advanced WPF concepts forced a solution that may not be the best one: I decided to use a ResourceDictionary.

The ResourceDictionary is damn near ubiquitous in WPF. Both FrameworkElement and FrameworkContentElement have a Resources property that allow you to store arbitrary .NET objects, so every control has a Resources property. This is often where styles or data sources are stored, but it can be any .NET object. You can also create your own ResourceDictionary as a standalone class, typically as App-level resources or as a Theme. The cool thing about ResourceDictionary, if you associate it with a class is that you can combine XAML and code like you do in a Window class. Since I’ve already got my AutoComplete class started, what I did was add a ResourceDictionary to my project and used the Class attribute (in the XAML namespace) to associate it with my AutoComplete class.

Now I have to write my own ControlTemplate for TextBox that will allow me to stick my ListBox to it. I could start from scratch, but then I’d have to recreate all the behaviour of the TextBox, including borders, colours, mouse over behaviour, etc, and I want to get this done. I have XamlPadX, so why not pull out the default TextBox style and manipulate it? It’s got the standard look and everything. So that’s what I do: stick that in my ResourceDictionary and change the template to add the ListBox, like this:

<ControlTemplate TargetType="TextBoxBase">
    <StackPanel>
        <mwt:ListBoxChrome Name="Bd">
            <ScrollViewer Name="PART_ContentHost" />
        </mwt:ListBoxChrome>
        <Popup x:Name="autoCompletePopup" 
               Placement="Bottom" 
               PlacementTarget="{Binding ElementName=Bd}"
               StaysOpen="False"
               AllowsTransparency="True">
            <ListBox x:Name="AutoCompleteListBox"
                     ItemsSource="{Binding Source={StaticResource viewSource}}" />
        </Popup>
    </StackPanel>
    <ControlTemplate.Triggers ...>
</ControlTemplate>

This is the relevant piece where I set the Template property on the Control. You can view the entire ResourceDictionary here (Or Download the source). It differs from the standard one in a few places: 1) The StackPanel that contains the TextBox and 2) the Popup containing the ListBox with the name AutoCompleteListBox. Why use the Popup? I’ll leave that as an exercise for the reader. 🙂 Note the ListBoxChrome element with the ScrollViewer inside it. The ListBoxChrome element resides in the Presenation.Aero assembly. Not listed is the Style.Resources property where I add the CollectionViewSource with the Filter event handled.

The methods for handling the CollectionViewSource.Filter and the TextBox.TextChanged events remain the same, I just have to move them to the AutoComplete class and hook them up to the TextBox when it’s passed to me in the OnSourcePropertyChanged event handler when my attached property changes, about which I mentioned earlier in Part 2. I did this with a private, read-only DependencyProperty that creates an AutoComplete instance to associate with the TextBox as the code below shows:

private static void OnSourcePropertyChanged(DependencyObject d, 
                                    DependencyPropertyChangedEventArgs e)
{
   AutoComplete ac = new AutoComplete();
   ac.TextBox = (Control)d;
   ac.ViewSource.Source = e.NewValue;
   d.SetValue(AutoCompleteInstancePropertyKey, ac);
}

internal Control TextBox
 {
    set 
    {
       control = value;
       Style s = (Style)this["autoCompleteTextBoxStyle"];
       viewSource = (CollectionViewSource)control.GetViewSource(s);
       viewSource.Filter += CollectionViewSource_Filter;
       value.SetValue(Control.StyleProperty, this["autoCompleteTextBoxStyle"]);
       value.ApplyTemplate();
       autoCompletePopup = (Popup) value.Template.FindName("autoCompletePopup", value);
       value.AddHandler(System.Windows.Controls.TextBox.TextChangedEvent, 
                                new TextChangedEventHandler(textBox1_TextChanged));
       value.LostFocus += textBox1_LostFocus;
       value.PreviewKeyUp += textBox1_PreviewKeyUp;
    }
 }

In the AutoComplete.TextBox setter is where I set the TextBox’s Style to my style and grab my CollectionViewSource and a reference to the Popup.

That’s essentially it. We’ve created an autocomplete TextBox in WPF! But what’s the point when you don’t take advantage of the new tech? Next time I’ll explain a couple of improvements we can make to the AutoComplete TextBox and show that adding support from ComboBox is really straightforward.