locked
Combobox with Auto Complete Facility in WPF RRS feed

  • Question

  • Hello Guys,

    I am trying to achive Auto Complete feature in Combo Box in WPF.

    I tried the using the below sample from this site.

    http://dotbay.blogspot.ae/2009/04/building-filtered-combobox-for-wpf.html

    it works fine when the combo box is not bound.

    when it is bound to any object data is show in the list.

    I used the below class to bind.

    FilteredComboBox1.ItemsSource = cat;
    FilteredComboBox1.DisplayMemberPath = "CategoryName";
    FilteredComboBox1.SelectedValuePath = "CategoryID";

    public class testData
        {
            private int _catID;
            private string _catName;
            public testData(int CategoryID, string CategoryName)
            {
                _catID = CategoryID;
                _catName = CategoryName;
            }
            public int CategoryID { get; set; }
            public string CategoryName { get; set; }
        }

    Please advice.

    regards

    James 


    Beginner

    Monday, June 3, 2013 3:56 PM

Answers

  • I'd go with Xceed's Extended Toolkit control, AutoCompleteTextBox myself.
    • Marked as answer by Min Zhu Monday, June 10, 2013 6:13 AM
    Tuesday, June 4, 2013 6:59 AM

All replies

  • i hope this will help you, i did in a different way.

     <ComboBox Width="200" x:Naem="cmbx" ItemsSource="{Binding Countries}" DisplayMemberPath="CountryName" IsEditable="True">
                                    <ComboBox.Style>
                                        <Style>
                                            <EventSetter Event="TextBox.TextChanged" Handler="TextBox_TextChanged" />
                                        </Style>
                                    </ComboBox.Style>
                                </ComboBox>

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Threading;
    using System.Xml.Linq;
    using System.Windows.Media.Animation;
    
    namespace WpfApplication2
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.Loaded += new RoutedEventHandler(MainWindowLoaded);
            }
    
            
            List<Country> _countries = new List<Country>();
          
    
            void MainWindowLoaded(object sender, RoutedEventArgs e)
            {
               cmbx.ItemsSource = _countries;
    
    
            
    
            }
    
         
        
    
            private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
            {
                var cmbx = sender as ComboBox;
                cmbx.ItemsSource = from item in _countries
                                   where item.CountryName.ToLower().Contains(cmbx.Text.ToLower())
                                   select item;
                cmbx.IsDropDownOpen = true;
            }
        }
    
     
    
        public class Country
        {
            public int CountryId { get; set; }
            public string CountryName { get; set; }
        }
    }
    


    Thanks & Regards
    Syed Amjad Sr. Silverlight/WPF Developer,
    yahoo : syedamjad6736@yahoo.com, skype : syedamjad.0786.
    Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

    Monday, June 3, 2013 6:30 PM
  • I'd go with Xceed's Extended Toolkit control, AutoCompleteTextBox myself.
    • Marked as answer by Min Zhu Monday, June 10, 2013 6:13 AM
    Tuesday, June 4, 2013 6:59 AM
  • Hi

    Your suggestion will hit the database on every text change event.

    better to go with caching then rite?

    regards

    James


    Beginner

    Tuesday, June 4, 2013 10:06 AM
  • Hi,

    i tried the wpftoolkit AutoCompleteTextBox and its working fine.

    but i i was wondering how to validate if the user selects a invalid item (Items not found in the list).

    Regards

    James


    Beginner

    Tuesday, June 4, 2013 10:09 AM
  • Hmm... I'm not super familar with that control to be honest. That said, if you don't want your users to be able to select something that isn't available, then perhaps you could just use a ComboBox with IsEditable set to true :)


    Wednesday, June 5, 2013 5:24 AM
  • James Alvin

    when you dont find any matching item in the database, i mean when query returns nothing, then you bind one item as default with some text saying "item not found", it will displayed in dropdown.

    let me know if you dont get me


    Thanks & Regards
    Syed Amjad Sr. Silverlight/WPF Developer,
    yahoo : syedamjad6736@yahoo.com, skype : syedamjad.0786.
    Please use Marked as Answer if my post solved your problem and use Vote As Helpful if a post was useful.

    Wednesday, June 5, 2013 5:53 AM
  • Thanks guys for the reply.

    I adapted with wpftoolkit AutoCompleteTextBox.


    Beginner

    • Marked as answer by James Alvin Monday, June 10, 2013 3:17 PM
    • Unmarked as answer by James Alvin Monday, June 10, 2013 3:17 PM
    Saturday, June 8, 2013 10:07 AM
  • Hi guys.

    This is how i used  AutoCompleteBox in WPFToolkit. (Of course with the help of Google Guru).

    Step 1 : Included the WPFToolkit in my Project

    Step 2 : I included the below class  (Change the name of AutoCompletetBox to AutoCompleteBoxEX.

    public class AutoCompleteBoxEx : AutoCompleteBox
        {
            private bool _selectorIsListBox = false;
            private bool _selectorSelectionChangedHandlerRegisterd = false;
            private const int SELECTOR_MAX_HEIGHT = 250;
            private TextBox _textBox;
            private ListBox _selector;
    
            public AutoCompleteBoxEx()
            {
                Loaded += AutoCompleteBoxExLoaded;
            }
    
    
    
            protected void AutoCompleteBoxExLoaded(object sender, System.Windows.RoutedEventArgs e)
            {
                if (_selector == null)
                {
                    _selector = Template.FindName("Selector", this) as ListBox;
    
                    if (_selector != null)
                        _selectorIsListBox = true;
                }
    
                if (!_selectorSelectionChangedHandlerRegisterd && _selectorIsListBox && _selector != null)
                {
                    _selector.SelectionChanged += ListBoxSelectionChanged;
                    _selector.MaxHeight = SELECTOR_MAX_HEIGHT;
                    _selectorSelectionChangedHandlerRegisterd = true;
                }
            }
    
    
    
            static void ListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                ListBox box = ((ListBox)sender);
                box.ScrollIntoView(box.SelectedItem);
                e.Handled = true;
            }
    
            protected override void OnPreviewTextInput(TextCompositionEventArgs e)
            {
                var source = this.ItemsSource as IEnumerable<string>;
                if (source == null)
                {
                    return;
                }
    
                if (!source.Any(x => x.StartsWith(this.Text + e.Text, true, CultureInfo.CurrentCulture)))
                {
                    e.Handled = true;
                }
                else
                {
                    base.OnPreviewTextInput(e);
                }
            }
        }

    Step 3 : Used the control (AutoCompleteBoxEX) in my WPF Window as below.

    Inside WPF Window Constructor

    InitializeComponent();

    DataClasses1DataContext db = new DataClasses1DataContext(); var q1 = (from p in db.Categories select p).Take(100); MyAutoCompleteBox.DataContext = q1; MyAutoCompleteBox.FilterMode = AutoCompleteFilterMode.Contains; MyAutoCompleteBox.SelectionChanged += new SelectionChangedEventHandler(MyAutoCompleteBox_SelectionChanged);

    // Handle the SelectionChanged event-setting the data context for the stack panel
            // that contains the details to the selected item.
            void MyAutoCompleteBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                if (e.AddedItems.Count > 0)
                {
                    Category cat = (Category)e.AddedItems[0];
                    MyAutoCompleteBox.Tag = cat.Category_ID.ToString();
                    txtCat.Text = MyAutoCompleteBox.Tag.ToString();
                }
                else
                {
                    MyAutoCompleteBox.Tag = "";
                    txtCat.Text = MyAutoCompleteBox.Tag.ToString();
                }
            }


    In XML

    <my:AutoCompleteBox x:Name="MyAutoCompleteBox"
                                    ItemsSource="{Binding}" 
                                    ValueMemberBinding="{Binding Path=Category_Name}">
                    <my:AutoCompleteBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Path=Category_Name}" />
                        </DataTemplate>
                    </my:AutoCompleteBox.ItemTemplate>
                </my:AutoCompleteBox>

    Please let me know if there is any better way to accomplish the same task.

    Thank You ALL!!


    Beginner

    Monday, June 10, 2013 3:10 PM