Solved

c# combobox autocomplete behavior

Posted on 2016-08-30
6
132 Views
Last Modified: 2016-08-31
Hi guys and girls,

I wrote an apps in c# and just found out that for some computer who need to stay in XP for compatibility reason (old soft), i have a different autocomplete behavior with combobox.

 wrote 351 and all my list starting with 351 appear like this

- What i want (and work perfectly on win7 and above)

351
351-A
3510
351C

- What i got with XP (SP3)

wrote 351 but as soon as i get the 1 i got this

351

Everyting in my list witch is not exacly 351 is not visible.

My combobox is autocompletemode = Suggest and autocompletesource = listitems. I also tried SuggestAppend and nothing change. If anyone have a clue i would appreciate !

Thank you
0
Comment
Question by:RichDu
  • 3
  • 3
6 Comments
 
LVL 33

Expert Comment

by:it_saige
ID: 41776936
Could you provide example code that recreates the issue?

-saige-
0
 

Author Comment

by:RichDu
ID: 41777000
Hi it_saige,

I would like to but i dont know which code i can provide. The combobox is filled by a SQL resquest. The setting of my combobox is ajusted with the properties tab.

If i press manually to access the list, everything is there in both OS. If i wrote in the combobox, than a list is made with the Suggest setting. The only difference is the fact that the list is not complete with XP as is it with win7.

If there's more info i can provide please dont hesitate !

Thank you
0
 
LVL 33

Expert Comment

by:it_saige
ID: 41777036
Let's start with how you fill your combobox.  You said it is filled by a SQL request.  Do you fill it directly from a datareader; e.g. -
while (reader.Read()) 
{
	combobox1.Items.Add(reader["SomeFieldName"].ToString());
}

Open in new window

Do you fill a list and set the list as a datasource for the combobox; e.g. -
List<SomeObject> objects = new List<SomeObject>()
while (reader.Read())
{
	objects.Add(new SomeObject() { SomeFieldName = reader["SomeFieldName"].ToString() });
}
combobox1.DataSource = objects;

Open in new window


This code would be important.  Also you mention settings adjusted by properties.  What are the settings you adjust and then verify that you do not make any changes to the properties of the control within other methods of your form, if you do, include those changes.

-saige-
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 

Author Comment

by:RichDu
ID: 41777052
there it is

try
            {
                SqlConnection read = Cts.Login.ConnectRead();

                SqlCommand mycom = read.CreateCommand();

                mycom.CommandText = "SELECT Selection " +
                     "FROM ItemsQuinc ORDER BY Selection ASC";

                SqlDataAdapter da = new SqlDataAdapter(mycom);

                DataSet dataSet = new DataSet();
                da.Fill(dataSet);

                itemComboBox.DataSource = dataSet.Tables[0];

                itemComboBox.DisplayMember = "Selection";

                read.Close();
                read.Dispose();

            }

            catch (SqlException ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
                return;
            }

Open in new window


The only oyher setting i've change is FormattingEnabled = true. All others setting ar by default.

Thank you !
0
 
LVL 33

Accepted Solution

by:
it_saige earned 500 total points
ID: 41778321
I unfortunately cannot replicate your issue using the ComboBox and Windows XP.  However, perhaps it is the mechanism internal to the combobox that is causing you grief.  See if this test project gives you any better behaviour:

Form1.cs -
using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;

namespace EE_Q28966499
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void OnLoad(object sender, EventArgs e)
		{
			DataSet set = new DataSet();
			set.Tables.Add((from i in Enumerable.Range(0, 20) select new { ID = i, FirstName = string.Format("{0}{1}", i % 5 == 0 ? "John" : i % 4 == 0 ? "Mary" : i % 3 == 0 ? "Paul" : i % 2 == 0 ? "Clarence" : "MaryJo", i), Birthdate = DateTime.Now.AddYears(-(9 * i)), IsWorking = (i & 1) == 0 }).ConvertToDataTable("AllPeople"));
			comboBox1.DataSource = set.Tables["AllPeople"].DefaultView;
			comboBox1.DisplayMember = "FirstName";
			comboBox1.PropertySelector = c => c.Cast<DataRowView>().Select(view => view["FirstName"].ToString());
			comboBox1.FilterRule = (item, text) => item.IndexOf(text.Trim(), StringComparison.OrdinalIgnoreCase) > -1;
		}

		private void OnKeyPress(object sender, KeyPressEventArgs e)
		{
			if (sender is ComboBox)
			{
				var cmb = sender as ComboBox;
				if (cmb.Equals(comboBox1) && cmb.SelectedItem != null)
				{
					listBox1.Items.Add((cmb.SelectedItem as DataRowView).Row["FirstName"].ToString());
				}
			}
		}
	}
}

Open in new window

Form1.Designer.cs -
namespace EE_Q28966499
{
	partial class Form1
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.IContainer components = null;

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
		protected override void Dispose(bool disposing)
		{
			if (disposing && (components != null))
			{
				components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Windows Form Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.comboBox1 = new EE_Q28966499.AutoCompleteComboBox();
			this.listBox1 = new System.Windows.Forms.ListBox();
			this.SuspendLayout();
			// 
			// comboBox1
			// 
			this.comboBox1.FilterRule = null;
			this.comboBox1.FormattingEnabled = true;
			this.comboBox1.Location = new System.Drawing.Point(13, 13);
			this.comboBox1.Name = "comboBox1";
			this.comboBox1.PropertySelector = null;
			this.comboBox1.Size = new System.Drawing.Size(259, 21);
			this.comboBox1.SuggestionBoxHeight = 96;
			this.comboBox1.SuggestionListOrderRule = null;
			this.comboBox1.TabIndex = 0;
			this.comboBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.OnKeyPress);
			// 
			// listBox1
			// 
			this.listBox1.FormattingEnabled = true;
			this.listBox1.Location = new System.Drawing.Point(13, 41);
			this.listBox1.Name = "listBox1";
			this.listBox1.Size = new System.Drawing.Size(259, 212);
			this.listBox1.TabIndex = 1;
			// 
			// Form1
			// 
			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			this.ClientSize = new System.Drawing.Size(284, 261);
			this.Controls.Add(this.listBox1);
			this.Controls.Add(this.comboBox1);
			this.Name = "Form1";
			this.Text = "Form1";
			this.Load += new System.EventHandler(this.OnLoad);
			this.ResumeLayout(false);

		}

		#endregion

		private AutoCompleteComboBox comboBox1;
		private System.Windows.Forms.ListBox listBox1;
	}
}

Open in new window

SupportingObjects.cs -
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Windows.Forms;

namespace EE_Q28966499
{
	static class Extensions
	{
		public static DataTable ConvertToDataTable<T>(this IEnumerable<T> source, string name = "")
		{
			DataTable table = string.IsNullOrWhiteSpace(name) ? new DataTable() : new DataTable(name);
			var properties = TypeDescriptor.GetProperties(typeof(T));
			foreach (PropertyDescriptor property in properties)
			{
				if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
					table.Columns.Add(property.Name, property.PropertyType.GetGenericArguments()[0]);
				else
					table.Columns.Add(property.Name, property.PropertyType);
			}

			object[] values = new object[properties.Count];
			foreach (var item in source)
			{
				for (int i = 0; i < properties.Count; i++)
					values[i] = properties[i].GetValue(item);
				table.Rows.Add(values);
			}
			return table;
		}
	}

	// Credit to PhysIcu$ for source - http://www.codeproject.com/Tips/631196/ComboBox-with-Suggest-Ability-based-on-Substring-S
	public sealed class AutoCompleteComboBox : ComboBox
	{
		#region fields and properties
		private readonly ListBox _suggestionBox = new ListBox { Visible = false, TabStop = false };
		private readonly BindingList<string> _suggestions = new BindingList<string>();
		private Expression<Func<ObjectCollection, IEnumerable<string>>> _propertySelector;
		private Func<ObjectCollection, IEnumerable<string>> _propertySelectorCompiled;
		private Expression<Func<string, string, bool>> _filterRule;
		private Func<string, bool> _filterRuleCompiled;
		private Expression<Func<string, string>> _suggestListOrderRule;
		private Func<string, string> _suggestListOrderRuleCompiled;

		/// <summary>Gets or sets the height of the suggestion box.</summary>
		/// <value>The height of the suggestion box.</value>
		public int SuggestionBoxHeight
		{
			get { return _suggestionBox.Height; }
			set
			{
				if (value > 0)
					_suggestionBox.Height = value;
			}
		}

		/// <summary>If the item-type of the ComboBox is not string, you can set here which property should be used</summary>
		public Expression<Func<ObjectCollection, IEnumerable<string>>> PropertySelector
		{
			get { return _propertySelector; }
			set
			{
				if (value == null) return;
				_propertySelector = value;
				_propertySelectorCompiled = value.Compile();
			}
		}

		///<summary>Lambda-Expression to determine the suggested items
		/// (as Expression here because simple lamda (func) is not serializable)
		/// <para>default: case-insensitive contains search</para>
		/// <para>1st string: list item</para>
		/// <para>2nd string: typed text</para>
		///</summary>
		public Expression<Func<string, string, bool>> FilterRule
		{
			get { return _filterRule; }
			set
			{
				if (value == null) return;
				_filterRule = value;
				_filterRuleCompiled = item => value.Compile()(item, Text);
			}
		}

		///<summary>
		/// Lambda-Expression to order the suggested items
		/// (as Expression here because simple lamda (func) is not serializable)
		/// <para>default: alphabetic ordering</para>
		///</summary>
		public Expression<Func<string, string>> SuggestionListOrderRule
		{
			get { return _suggestListOrderRule; }
			set
			{
				if (value == null) return;
				_suggestListOrderRule = value;
				_suggestListOrderRuleCompiled = value.Compile();
			}
		}

		#endregion

		/// <summary>Initializes a new instance of the <see cref="AutoCompleteComboBox"/> class.</summary>
		public AutoCompleteComboBox()
		{
			// set the standard rules:
			_filterRuleCompiled = s => s.ToLower().Contains(Text.Trim().ToLower());
			_suggestListOrderRuleCompiled = s => s;
			_propertySelectorCompiled = collection => collection.Cast<string>();

			_suggestionBox.DataSource = _suggestions;
			_suggestionBox.Click += OnClick;

			ParentChanged += OnParentChanged;
		}

		/// <summary>Raises the <see cref="E:System.Windows.Forms.Control.TextChanged" /> event.</summary>
		/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
		protected override void OnTextChanged(EventArgs e)
		{
			base.OnTextChanged(e);

			if (!Focused) return;

			_suggestions.Clear();
			_suggestions.RaiseListChangedEvents = false;
			_propertySelectorCompiled(Items)
				.Where(_filterRuleCompiled)
				.OrderBy(_suggestListOrderRuleCompiled)
				.ToList()
				.ForEach(_suggestions.Add);
			_suggestions.RaiseListChangedEvents = true;
			_suggestions.ResetBindings();

			_suggestionBox.Visible = _suggestions.Any();

			if (_suggestions.Count == 1 &&
						_suggestions.Single().Length == Text.Trim().Length)
			{
				Text = _suggestions.Single();
				Select(0, Text.Length);
				_suggestionBox.Visible = false;
			}
		}

		#region size and position of suggest box

		/// <summary>Handles the <see cref="E:ParentChanged" /> event.</summary>
		/// <param name="sender">The sender.</param>
		/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
		private void OnParentChanged(object sender, EventArgs e)
		{
			Parent.Controls.Add(_suggestionBox);
			Parent.Controls.SetChildIndex(_suggestionBox, 0);
			_suggestionBox.Top = Top + Height - 3;
			_suggestionBox.Left = Left + 3;
			_suggestionBox.Width = Width - 20;
			_suggestionBox.Font = new Font("Segoe UI", 9);
		}

		/// <summary>Raises the <see cref="E:System.Windows.Forms.Control.LocationChanged" /> event.</summary>
		/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
		protected override void OnLocationChanged(EventArgs e)
		{
			base.OnLocationChanged(e);
			_suggestionBox.Top = Top + Height - 3;
			_suggestionBox.Left = Left + 3;
		}

		/// <summary>Raises the <see cref="E:System.Windows.Forms.Control.SizeChanged" /> event.</summary>
		/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
		protected override void OnSizeChanged(EventArgs e)
		{
			base.OnSizeChanged(e);
			_suggestionBox.Width = Width - 20;
		}

		#endregion

		#region visibility of suggest box

		/// <summary>Raises the <see cref="E:System.Windows.Forms.Control.LostFocus" /> event.</summary>
		/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
		protected override void OnLostFocus(EventArgs e)
		{
			// _suggLb can only getting focused by clicking (because TabStop is off)
			// --> click-eventhandler 'SuggLbOnClick' is called
			if (!_suggestionBox.Focused)
				HideSuggestionBox();
			base.OnLostFocus(e);
		}

		/// <summary>Handles the <see cref="E:Click" /> event.</summary>
		/// <param name="sender">The sender.</param>
		/// <param name="eventArgs">The <see cref="EventArgs"/> instance containing the event data.</param>
		private void OnClick(object sender, EventArgs eventArgs)
		{
			Text = _suggestionBox.Text;
			Focus();
		}

		/// <summary>Hides the suggestion box.</summary>
		private void HideSuggestionBox()
		{
			_suggestionBox.Visible = false;
		}

		/// <summary>Raises the <see cref="E:System.Windows.Forms.ComboBox.DropDown" /> event.</summary>
		/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
		protected override void OnDropDown(EventArgs e)
		{
			HideSuggestionBox();
			base.OnDropDown(e);
		}

		#endregion

		#region keystroke events

		/// <summary>Raises the <see cref="E:System.Windows.Forms.Control.PreviewKeyDown" /> event.</summary>
		/// <param name="e">A <see cref="T:System.Windows.Forms.PreviewKeyDownEventArgs" /> that contains the event data.</param>
		protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
		{
			if (!_suggestionBox.Visible)
			{
				base.OnPreviewKeyDown(e);
				return;
			}

			switch (e.KeyCode)
			{
				case Keys.Down:
					if (_suggestionBox.SelectedIndex < _suggestions.Count - 1)
						_suggestionBox.SelectedIndex++;
					return;
				case Keys.Up:
					if (_suggestionBox.SelectedIndex > 0)
						_suggestionBox.SelectedIndex--;
					return;
				case Keys.Enter:
					Text = _suggestionBox.Text;
					Select(0, Text.Length);
					_suggestionBox.Visible = false;
					return;
				case Keys.Escape:
					HideSuggestionBox();
					return;
			}

			base.OnPreviewKeyDown(e);
		}

		/// <summary>The keys to handle</summary>
		private static readonly Keys[] KeysToHandle = new[] { Keys.Down, Keys.Up, Keys.Enter, Keys.Escape };

		/// <summary>Processes a command key.</summary>
		/// <param name="msg">A <see cref="T:System.Windows.Forms.Message" />, passed by reference, that represents the window message to process.</param>
		/// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys" /> values that represents the key to process.</param>
		/// <returns>true if the character was processed by the control; otherwise, false.</returns>
		protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
		{
			// the keysstrokes of our interest should not be processed be base class:
			if (_suggestionBox.Visible && KeysToHandle.Contains(keyData))
				return true;
			return base.ProcessCmdKey(ref msg, keyData);
		}
		#endregion
	}
}

Open in new window

Which produces the following output -

Initial load -Capture.JPGAfter typing 'jo' -Capture.JPG
Any item in the source that contains 'jo' is returned.

-saige-
0
 

Author Comment

by:RichDu
ID: 41778604
Hi saige,

It works perfectly !!!

i will have to understand why the properties setting wont work but the way you make it work well.

Thanks again for your time :)
0

Featured Post

Master Your Team's Linux and Cloud Stack!

The average business loses $13.5M per year to ineffective training (per 1,000 employees). Keep ahead of the competition and combine in-person quality with online cost and flexibility by training with Linux Academy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

773 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question