views:

55

answers:

1

I'm not sure why, but none of the solutions are working properly for me from a similar question.

I realize that a TextBox has a property (CharacterCasing) which can be set to Upper to change any lowercase typing into uppercase. It works so great because the user is never interrupted while typing, caps lock and shift don't affect it negatively, and other non-alpha characters aren't affected negatively either.

The problem is that there is no option to use this property for a ComboBox. The solutions from that similar posting don't seem to work for me. I'm looking to duplicate the CharacterCasing property but for a ComboBox. I don't mind it being an attached property, in fact, that'd be great. I tried a couple of different events directly on the xaml object, with no success.

+3  A: 

The ComboBox template uses a TextBox when IsEditable is true. So you can either replace the template to set CharacterCasing on the TextBox, or create an attached property that will find the TextBox by its name ("PART_EditableTextBox") and set the CharacterCasing property on it.

Here's a simple implementation of the attached property solution:

public static class ComboBoxBehavior
{

    [AttachedPropertyBrowsableForType(typeof(ComboBox))]
    public static CharacterCasing GetCharacterCasing(ComboBox comboBox)
    {
        return (CharacterCasing)comboBox.GetValue(CharacterCasingProperty);
    }

    public static void SetCharacterCasing(ComboBox comboBox, CharacterCasing value)
    {
        comboBox.SetValue(CharacterCasingProperty, value);
    }

    // Using a DependencyProperty as the backing store for CharacterCasing.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CharacterCasingProperty =
        DependencyProperty.RegisterAttached(
            "CharacterCasing",
            typeof(CharacterCasing),
            typeof(ComboBoxBehavior),
            new UIPropertyMetadata(
                CharacterCasing.Normal,
                OnCharacterCasingChanged));

    private static void OnCharacterCasingChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
    {
        var comboBox = o as ComboBox;
        if (comboBox == null)
            return;

        if (comboBox.IsLoaded)
        {
            ApplyCharacterCasing(comboBox);
        }
        else
        {
            comboBox.Loaded += new RoutedEventHandler(comboBox_Loaded);
        }
    }

    private static void comboBox_Loaded(object sender, RoutedEventArgs e)
    {
        var comboBox = sender as ComboBox;
        if (comboBox == null)
            return;

        ApplyCharacterCasing(comboBox);
        comboBox.Loaded -= comboBox_Loaded;
    }

    private static void ApplyCharacterCasing(ComboBox comboBox)
    {
        var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;
        if (textBox != null)
        {
            textBox.CharacterCasing = GetCharacterCasing(comboBox);
        }
    }

}

And here's how to use it:

    <ComboBox ItemsSource="{Binding Items}"
              IsEditable="True"
              local:ComboBoxBehavior.CharacterCasing="Upper">
        ...
Thomas Levesque
This doesn't seem to be working for me... is it not usable in a User Control? In particular the line `var textBox = comboBox.Template.FindName("PART_EditableTextBox", comboBox) as TextBox;` sets textBox as null, which is why the `CharacterCasing` never gets applied.
myermian
That's weird... I tested it and it worked fine for me. Did you set IsEditable to true ? If it's false, the ComboBox uses a different template, which doesn't contain a TextBox
Thomas Levesque
I'm not sure why it isn't working either. I put a debugging stop on that line and checked the properties of comboBox. IsEditable is set to true.
myermian