web 2.0

Tinkering with a Editable ComboBox

I started my project wanting to make a very fancy WPF ComboBox.  I learned from my pervious WPF experiences that the framework is look-less and it’s better to use styles and templates to draw out the behavior you want.  After working for hours, I realized that a simple ComboBox that drops down and allows you to start typing the first few letters of what you want would be the coolest.

Here is all of my XAML code:

<Grid>
    <Grid.Resources>
        <CollectionViewSource Source="{Binding MyObjects}" x:Key="ObjectsSource">
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="Name" />
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
    </Grid.Resources>
    <ComboBox IsTextSearchEnabled="True" VerticalAlignment="Top" TextSearch.TextPath="Name" 
              IsEditable="True" StaysOpenOnEdit="True" ItemsSource="{Binding Source={StaticResource ObjectsSource}}"  
              IsDropDownOpen="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}, Mode=OneWay}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>
</Grid>

Let’s look at a few things:

  1. Yes, I put my CollectionViewSource in the Resources.  This was a requirement of the project I was working on but I know it’s better form to do this instead:
    <ComboBox.ItemsSource>
     <Binding>
         <Binding.Source>
             <CollectionViewSource...>
             </CollectionViewSource>
         </Binding.Source>
     </Binding>
    </ComboBox.ItemsSource>

    I understand that it’s a matter of preference, but I think both are good ways of handling this.  I prefer the resources method in case I have to use that collection again with another element.  If your ObjectCollection is just a property of some greater object, I would set the entire Grid’s DataContext to your big Object and use the nested hierarchy to set the CollectionViewSource’s Source (tongue-twister there!).

  2. I set both IsTextSearchEnabled to True and IsEditable to True.  This is a well known way of allowing a user to Search for items in your ComboBox without having to write custom code.  It’s slick and does not require any code-behind.
  3. I set the TextSearch.TextPath equal to the Object’s “Name” property and bound the TextBlock within the ItemTemplate to “Name”.  This is for an important reason.  If you don’t set any parameters such as DisplayMemberPath or the TextSearch attached properties, you will find that the ComboBox automatically displays the value returned from your custom object’s ToString() method.  If you just set the DisplayMemberPath property you will get this issue:

    image

    If you just set the ItemTemplate property to show some data you will run into this issue:

    image

    Unfortunately, we’re not allowed to Set both the DisplayMemberPath and ItemTemplate properties.  My workaround, which is not ugly, is to set the TextSearch.TextPath property.  This has a similar effect to DisplayMemberPath, but also gives me the opportunity to set my ItemTemplate to anything that I want.  Clean and cool!  Most people online would advise you to override ToString() and set it to a new value or use an IValueConverter to convert your custom object to a string.  I believe this is bad practice, you should never have to change your objects or business logic to suit your user interface.  Worse yet, you should not have to keep any of your UI logic within your objects.

  4. I really surprised when I found out that the ComboBox does not automatically open when you start typing.  I quickly remedied this by binding IsDropDownOpen property to it’s IsKeyboardFocusWithin property.  It took me hours to figure this out, but the ComboBox has an IsFocused and IsKeyboardFocused property.  These properties do not behave in the way that you expect.  When you click on the ComboBox, you are actually clicking in a TextBox that is the child of the ComboBox.  So the ComboBox itself is not focused but a child of the ComboBox is focused.  Thankfully, the API includes a property (IsKeyboardFocusWithin) that tells you whether any of the children of the ComboBox on the visual tree are focused.  This came in very handy with my implementation.

This is the best I could do in one day’s work.  Give me some feedback, I really want to know how someone would improve this ComboBox.  My goal is to give it as many features as possible without having to resort to code-behind.  I placed the items in a CollectionViewSource so that later Filtering or Grouping could be implemented.  It would be cool to see if someone could do live in-place filtering so that this ComboBox would behave like a Windows Forms auto-complete box.  Enjoy!

Tags: ,

WPF | .NET

Comments

vreauforum.com , on 2/16/2010 2:17:20 PM Said:

pingback

Pingback from vreauforum.com

VreauForum.com  » Blog Archive   » SeeSharpRun.NET | Tinkering with a Editable ComboBox

Sean Prue United States, on 2/18/2010 8:58:54 AM Said:

Sean Prue

If you don't mind me asking I just wanted to find out on what is the difference between blogenenigne and wordpress blogs? Is it easier to use or more efficient? I amseeing a lot of blogs powered by this software popping up lately and wondering if it is better or not? Thanks...

Datingportale , on 4/18/2010 2:59:56 AM Said:

Datingportale

Dear my friend, your weblog is truly good, but what the aspx ending of all the pages intends? I only know php and xml. Is aspx critical?