Solved

c# combobox autocomplete behavior

Posted on 2016-08-30
6
92 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 32

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 32

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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

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 32

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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

A short article about a problem I had getting the GPS LocationListener working.
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
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 seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

746 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now