ComboBox with Editable Textbox

Looking for a ComboBox that has an editable textbox - allowing you to either pick a pre-selected item or enter something else? Here’s a simple implementation.

Background

Turns out that, as of WinRT (Windows 8) and onwards, ComboBoxes have a (read-only) textblock field. This is a pain if you wanted to handle the scenario where users could either select a pre-existing item or type in something different.

I have seen a few implementations floating around where, in the ComboBoxItems, the first item was always an editabled TextBox. If you entered text it would then add to the list. But this still wasn’t the behaviour I was after.

ComboBoxTextBoxControl

I created a user control that gives me behaviour I’m after, as seen below.

Combo textbox sample

In a nutshell, what I did was:

  • Create a UserControl I called ComboBoxTextBoxControl
  • Added a ComboBox and TextBox
  • Modified the TextBox template to remove the delete button (the X that shows up in the right when you have text)
  • Modified the ComboBox template so that there is no border, background and the minimum width is 32
  • In code-behind, if you selected an item it would put the content into the textbox
  • Added properties to accept a binding (i.e. a list of pets) and to get what was selected (so we can bind this in the form)

The Code

Here you go. It’s long but only because of the custom templates. Once you get past that, you’ll see that the rest of my code is quite simple.

Firstly, here is the code behind

[code lang="csharp”] using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data;

namespace MyCode.Controls { /// /// UserControl where a ComboBox also has an editable TextBox ///

public sealed partial class ComboBoxWithTextBox : UserControl { public ComboBoxWithTextBox() { InitializeComponent(); }

public object ComboBoxTextItems { set { comboBox.SetBinding(ItemsControl.ItemsSourceProperty, value as Binding); } }

public object SelectedComboBoxTextItem { set { textBox.SetBinding(TextBox.TextProperty, value as Binding);} }

private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { textBox.Text = comboBox.SelectedItem as string; } } } [/code]

Here’s the XAML

[code lang="xml”]

<UserControl.Resources> <Setter.Value> </Setter.Value> <Setter.Value> <Grid.ColumnDefinitions> </Grid.ColumnDefinitions> <Grid.RowDefinitions> </Grid.RowDefinitions> <VisualStateManager.VisualStateGroups> <DiscreteObjectKeyFrame.Value> Visible </DiscreteObjectKeyFrame.Value> </VisualStateManager.VisualStateGroups> </Setter.Value>

</Grid.Resources> <Grid.ColumnDefinitions> </Grid.ColumnDefinitions> <Grid.RowDefinitions> </Grid.RowDefinitions> <VisualStateManager.VisualStateGroups> </VisualStateManager.VisualStateGroups> </Setter.Value>

</UserControl.Resources>

<Grid.ColumnDefinitions> </Grid.ColumnDefinitions>

[/code]

And finally here is the code showing how you could use it in your XAML page

[code lang="xml”] <controls:ComboBoxWithTextBox ComboBoxTextItems=”{Binding PetTypes}” SelectedComboBoxTextItem=”{Binding SelectedPet, Mode=TwoWay}” Width="150” HorizontalAlignment="Left” />

[/code]