Click here to Skip to main content
Click here to Skip to main content

Tagged as

I love behaving

, 8 Jun 2010
Rate this:
Please Sign up or sign in to vote.
Using Attached Behaviors to modify the behaviour of a TextBox

Some poor chap posted a question on CodeProject 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).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pete O'Hanlon
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.
 
I am not the Stig, but I do wish I had Lotus Tuned Suspension.
Follow on   Twitter   Google+

Comments and Discussions

 
QuestionCharacterCasing? PinmemberRichard Deeming17-Jun-10 8:53 
AnswerRe: CharacterCasing? PinmvpPete O'Hanlon17-Jun-10 9:25 
GeneralMessage Removed Pinmember_beauw_8-Jun-10 14:45 
GeneralRe: Formatting PinmvpPete O'Hanlon8-Jun-10 22:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 9 Jun 2010
Article Copyright 2010 by Pete O'Hanlon
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid