Home > behavior > I love behaving

I love behaving

Some poor chap posted a question on Code Project asking how to convert a textbox to be lower or upper case. My initial reaction to this (as with so much else), is to use MVVM and just handle the property change. I nearly posted this, but then I decided not to – instead, in this post I’d like to demonstrate the use of attached behaviours (or behaviors for those who don’t like the u).

An attached behaviour allows us to do things without having to depend on other items, such as a trigger or actions. Now, there’s a handy class added to the System.Windows.Interactivity dll called Behavior. We derive from this to add the behaviour to a particular control type. In this example, we’re going to hook into a TextBox and add the functionality that we want to automatically handle the upper/lower casing as appropriate.

In the first part, we’re going to add a DependencyProperty that will accept the boolean to indicate whether or not it should be all upper or lower case (yes, I know that it would be better to use an enumeration here, but this is just a sample to demonstrate the functionality).

public static readonly DependencyProperty UpperLowerMaskProperty =
  DependencyProperty.Register("UpperLowerMask", typeof(bool), typeof(UpperOrLowerBehavior), null);
public bool UpperLowerMask
{
   get { return (bool)GetValue(UpperLowerMaskProperty); }
   set { SetValue(UpperLowerMaskProperty, value); }
}

As you can see, there’s nothing particularly frightening about the code so far. It’s a DP like any other that we’ve created before. Now, we’ve derived from Behavior, so we need to override the OnAttached and OnDetached methods to hook/unregister the events that we’re interested in from the TextBox. The code to do this is shown here:

protected override void OnAttached()
{
  base.OnAttached();
  AssociatedObject.PreviewKeyDown += new KeyEventHandler(AssociatedObject_PreviewKeyDown);
  AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
  DataObject.AddPastingHandler(AssociatedObject, PastingHandler);
}
protected override void OnDetaching()
{
  base.OnDetaching();
  AssociatedObject.PreviewKeyDown -= new KeyEventHandler(AssociatedObject_PreviewKeyDown);
  AssociatedObject.TextChanged -= new TextChangedEventHandler(AssociatedObject_TextChanged);
  DataObject.RemovePastingHandler(AssociatedObject, PastingHandler);
}
As you can see, there are three things that we are interested in; the PreviewKeyDown, TextChanged events, and the paste handler. PreviewKeyDown is used to identify whether or not we want to handle the text changing, and retrieving the cursor position at that point in time. TextChanged is used to handle the text being changed.

The code for these looks a lot like this:

void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
{
  if (!_shouldBeCaptured) return;
  if (UpperLowerMask)
  {
    AssociatedObject.Text = AssociatedObject.Text.ToUpperInvariant();
  }
  else
  {
    AssociatedObject.Text = AssociatedObject.Text.ToLowerInvariant();
  }
  AssociatedObject.SelectionStart = _keyPos + 1;
}
void AssociatedObject_PreviewKeyDown(object sender, KeyEventArgs e)
{
  char key;
  char.TryParse(e.Key.ToString(), out key);
  _shouldBeCaptured = Keyboard.Modifiers == ModifierKeys.None && Char.IsLetter(key) ;
  _keyPos = AssociatedObject.SelectionStart;
}

Again, as you can see, there’s nothing particularly scary here. The AssociatedObject identifies the TextBox that we’re working on. Now that we have the behaviour, we need to use it. This means that we need to hook it into the XAML; here’s the page that we’re working with:

<Window x:Class="AllLowerOrUpper.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:behavior="clr-namespace:AllLowerOrUpper"
   xmlns:interact="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
   Title="Upper/Lower Behavior" Height="350" Width="525">
   <StackPanel>
     <TextBox Width="500" >
       <interact:Interaction.Behaviors>
         <behavior:UpperOrLowerBehavior UpperLowerMask="true" />
       </interact:Interaction.Behaviors>
     </TextBox>
     <TextBox Width="500" >
       <interact:Interaction.Behaviors>
          <behavior:UpperOrLowerBehavior UpperLowerMask="false" />
       </interact:Interaction.Behaviors>
     </TextBox>
   </StackPanel>
</Window>

And that’s it – a simple attached behavior to cope with the upper/lower functionality. It’s not perfect code, it’s intended to demonstrate the use of attached behaviors, so please add whatever functionality you need. Feel free to download the related sample (and don’t forget to rename the .doc file to .zip to get round the WordPress allowed files issue).

About these ads
Categories: behavior Tags:
  1. Abraham Heidebrecht
    June 10, 2010 at 3:47 pm

    I love behaviors as much as everybody else, but for this problem, why not use the TextBox’s CharacterCasing property? It already handles this for you. Unless this is Silverlight, in which case it isn’t available (but neither is the PreviewKeyDown event).

    • peteohanlon
      June 10, 2010 at 9:07 pm

      Sometimes, it’s the simplest things in life that trip you up. Thanks Abraham, I wasn’t aware of the CharacterCasing property; thanks for the info.

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Canny Coder

Java 8 Functional Programming with Lambda Expressions

pihole.org

Adventures in theoretical computer science, with your host, chaiguy1337

Confessions of a coder

Confessions of a WPF lover

WordPress.com

WordPress.com is the best place for your personal blog or business site.

Follow

Get every new post delivered to your Inbox.

Join 38 other followers

%d bloggers like this: