locked
ComboBox with text search?

    Question

  • I'm populating a standard ComboBox with a number of data items. I have set DisplayMemberPath and SelectedValuePath appropriately.  The problem is that when the ComboBox has focus, I want to be able to type a letter like 'm' and have it cycle through the display items that start with letter M.  In WPF we were able to accomplish this with TextSearch.TextPath.  Is anything like this supported in WinRT's ComboBox?  It's a major usability drawback for keyboard users if it's not supported.

    actiprosoftware.com - Professional WPF, WinRT, Silverlight, and WinForms UI controls and components

    Friday, June 20, 2014 2:45 PM

Answers

All replies

  • Hi,

    In windows store app, TextSearch.TextPath cannot be supported. But you can edit the DataTemplate of Combobox, set the SearchBox control in it. Then add the  search suggestions in the SearchBox. You can refer to the link to get more information:

    http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868180.aspx

    And see SearchBox control sample

    Best Wishes!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey. Thanks<br/> MSDN Community Support<br/> <br/> Please remember to &quot;Mark as Answer&quot; the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Monday, June 23, 2014 1:54 AM
  • Hello and thank you for the suggestion but that doesn't really help me. I have a ComboBox control and I want to use the ComboBox UI, not a SearchBox UI. My ComboBox only has a handful of items in it. With text search features found in other frameworks like WPF and Silverlight, we could simply type the first letter of a known item and have it get auto-selected.  In WinRT, since that simple feature isn't supported, we have to click the box and select an item with mouse/touch, or if only using keyboard, use up/down arrows to scroll through the list.  It's not efficient for keyboard users.

    actiprosoftware.com - Professional WPF, WinRT, Silverlight, and WinForms UI controls and components

    Monday, June 23, 2014 2:53 AM
  • Hi,

    I do not quite familiar with the TextSearch.TextPath in WPF. But as far as I know, you should set the Iseditable property of combobox to true when you use the TextSearch.TextPath in WPF. But in windows store app, the ComboBox.IsEditable propertyis readonly and always return false. In windows store app, combobox represents a selection control that combines a no-editable text box and a drop-down list box that allows users to select an item from a list. So you cannot do that in combobox in windows store app. You should define a custom control which similar with the combobox in WPF by yourself.

    Best Wishes!


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey. Thanks<br/> MSDN Community Support<br/> <br/> Please remember to &quot;Mark as Answer&quot; the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Monday, June 23, 2014 6:15 AM
  • Even without using TextSearch at all, in WPF I can do this:

    <ComboBox>
    	<ComboBoxItem>AAA</ComboBoxItem>
    	<ComboBoxItem>BBB</ComboBoxItem>
    	<ComboBoxItem>CCC</ComboBoxItem>
    </ComboBox>
    <ComboBox IsEditable="True">
    	<ComboBoxItem>AAA</ComboBoxItem>
    	<ComboBoxItem>BBB</ComboBoxItem>
    	<ComboBoxItem>CCC</ComboBoxItem>
    </ComboBox>
    

    In both of those cases (even the non-editable one), when the control has focus, I can press "B" and the BBB item will be selected.  That is the behavior that should be in the WinRT controls as well and isn't.  Pressing "B" in the WinRT control does nothing.


    actiprosoftware.com - Professional WPF, WinRT, Silverlight, and WinForms UI controls and components

    Monday, June 23, 2014 11:16 AM
  • Hi,
    Maybe something like Auto Complete Box will help you.

    Regards,


    Ibraheem Osama Mohamed | My Blog | @IbraheemOM | My Website

    (If my reply answers your question, please propose it as an answer)

    Monday, June 23, 2014 8:47 PM
  • Bill, after searching the internet for something like this, I designed my own user control. It is not perfect, and maybe not exactly what you need, but maybe this is a good start.

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using Windows.System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Input;
    
    namespace eMoyoConnect.Controls
    {
        public class SearchableComboBox : ComboBox
        {
    
            public ObservableCollection<string> ItemsSourceList
            {
                get { return (ObservableCollection<string>)GetValue(ItemsSourceListProperty); }
                set
                {
                    SetValue(ItemsSourceListProperty, value);
                    this.ItemsSource = ItemsSourceList;
                }
            }
    
            public static readonly DependencyProperty ItemsSourceListProperty =
                DependencyProperty.Register("ItemsSourceList", typeof(ObservableCollection<string>), typeof(SearchableComboBox),
                new PropertyMetadata(null, ItemsSourceListChanged));
    
            private static void ItemsSourceListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var plv = d as SearchableComboBox;
                plv.ItemsSource = e.NewValue;
            }
    
            public Collection<string> ItemsSourceListBase
            {
                get { return (Collection<string>)GetValue(ItemsSourceListBaseProperty); }
                set
                {
                    SetValue(ItemsSourceListBaseProperty, value);
                    this.ItemsSource = ItemsSourceListBase;
                }
            }
    
            public static readonly DependencyProperty ItemsSourceListBaseProperty =
                DependencyProperty.Register("ItemsSourceListBase", typeof(Collection<string>), typeof(SearchableComboBox),
                new PropertyMetadata(null, ItemsSourceListBaseChanged));
    
            private static void ItemsSourceListBaseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var plv = d as SearchableComboBox;
                plv.ItemsSource = e.NewValue;
            }
    
            string FilterString = "";
            protected override void OnKeyDown(KeyRoutedEventArgs e)
            {
                if (IsLetterOrSpace(e.Key))
                {
                    if (e.Key == VirtualKey.Space)
                        FilterString += " ";
                    else
                        FilterString += e.Key.ToString();
                    FilterList(FilterString);
                    this.ItemsSource = ItemsSourceList;
                    if (ItemsSourceList.Count > 0)
                        this.SelectedIndex = 0;
                }
                else if (e.Key == VirtualKey.Back)
                {
                    if (FilterString.Length > 0)
                    {
                        FilterString = FilterString.Substring(0, FilterString.Length - 1);
                        FilterList(FilterString);
                        this.ItemsSource = ItemsSourceList;
                        if (ItemsSourceList.Count > 0)
                            this.SelectedIndex = 0;
                    }
                }
    
                if (e.Key != VirtualKey.Space)
                {
                    base.OnKeyDown(e);
                }
            }
    
            protected override void OnGotFocus(RoutedEventArgs e)
            {
                string selectedValue = "";
                if (this.SelectedValue != null)
                    selectedValue = (string)this.SelectedValue;
                FilterString = "";
                FilterList(FilterString);
                if (!string.IsNullOrEmpty(selectedValue))
                    this.SelectedValue = selectedValue;
            }
    
            internal void FilterList(string FilterString)
            {
                ItemsSourceList.Clear();
                IEnumerable<string> list;
                if (!string.IsNullOrEmpty(FilterString))
                    list = ItemsSourceListBase.Where(x => x.StartsWith(FilterString));
                else
                    list = ItemsSourceListBase;
                foreach (var item in list)
                    ItemsSourceList.Add(item);
            }
    
            private bool IsLetterOrSpace(VirtualKey key)
            {
                return (key == VirtualKey.A
                    || key == VirtualKey.B
                    || key == VirtualKey.C
                    || key == VirtualKey.D
                    || key == VirtualKey.E
                    || key == VirtualKey.F
                    || key == VirtualKey.G
                    || key == VirtualKey.H
                    || key == VirtualKey.I
                    || key == VirtualKey.J
                    || key == VirtualKey.K
                    || key == VirtualKey.L
                    || key == VirtualKey.M
                    || key == VirtualKey.N
                    || key == VirtualKey.O
                    || key == VirtualKey.P
                    || key == VirtualKey.Q
                    || key == VirtualKey.R
                    || key == VirtualKey.S
                    || key == VirtualKey.T
                    || key == VirtualKey.U
                    || key == VirtualKey.V
                    || key == VirtualKey.W
                    || key == VirtualKey.X
                    || key == VirtualKey.Y
                    || key == VirtualKey.Z
                    || key == VirtualKey.Space);
            }
        }
    }
    

    You would define a new control like this:

    <control:SearchableComboBox Margin='5'
              x:Name='ComboBoxCountry'
              ItemsSourceList='{Binding CountryList}'
              ItemsSourceListBase='{Binding CountryListBase}'
              PlaceholderText='Select Country'/>

    Unfortunately you still need to provide a duplicate list CountryListBase. If you have suggestions on improving this, let me know!


    Monday, December 22, 2014 10:23 AM