Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Windows Forms / WinForm Controls / January 2007

Tip: Looking for answers? Try searching our database.

AutoComplete ComboBox with DroppedDown=true

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
aferriere - 12 Jan 2007 16:29 GMT
Hi
I have create an autocomplete combobox in VS.NET 1.1 based on some
articles I found on the net. Every thing works fine except when you
turn on DroppedDown=true to make the combo behave like an IE
autocomplete combobox. The combox seems to be working fine but when you
try to get combobox.Text or combobox.SelectedIndex through code they
point to the previous selection instead of showing the value currently
selected. Any one figure out how to get around this issue ????

Below is the code. If you comment the line DroppedDown=true; everything
should work fine. But if you leave it there you can reproduce the above
problem.

public class ACComboBox : System.Windows.Forms.ComboBox
    {
        public ACComboBox():base()
        {
        }

        protected override void
OnKeyPress(System.Windows.Forms.KeyPressEventArgs e)
        {
            DroppedDown=true;
            if (char.IsControl(e.KeyChar))
                return;

            string ToFind = Text.Substring(0,SelectionStart) + e.KeyChar;
            int Index = FindStringExact(ToFind);
            if (Index == -1)
                Index = FindString(ToFind);

            if (Index == -1)
                return;

            SelectedIndex = Index;
            SelectionStart = ToFind.Length;
            SelectionLength = Text.Length - SelectionStart;
            e.Handled = true;
            base.OnKeyPress(e);
        }

        protected override void OnLeave(System.EventArgs e)
        {
            string text=Text;
            int index=FindStringExact(text,-1);
            if(index<0)
                index=0;

            SelectedIndex = index;                       
            base.OnLeave(e);
        }
    }
Bryan Phillips - 15 Jan 2007 11:14 GMT
I was unable to reproduce the problem using a simple form with your
ACComboBox and a button.  Can you post a little more code so I can
continue looking at the problem?

Thanks,

--
Bryan Phillips
MCSD, MCDBA, MCSE
Blog:  http://bphillips76.spaces.live.com

> Hi
> I have create an autocomplete combobox in VS.NET 1.1 based on some
[quoted text clipped - 48 lines]
>         }
>     }
aferriere - 16 Jan 2007 16:27 GMT
Hi Bryan

Thanks for responding. I should have been more specific as to how to
recreate the problem.
Just to let you know I am using a DataBound combobox bound to the lname
field of the employee table from pubs DB.

The way to recreat the problem is that you have to use your keyboard
only when you are selecting items in the combobox. when you use the
mouse things work fine. So for eg: use your TAB key to get to the
combobox. Then for eg type any letter lets say 'M' the combox selected
text changes to the first Name which starts with 'M' and then Tab out
again to the button. Click the button now on the code behind the
combobox SelectedIndex,etc.. point to previously selected item. Also if
you use your arrow keys to choose the combobox items things work fine.
So you have to just use the letter keys to select an item and then tab
out to the button to reproduce the error.

Hope my expanation makes more sense this time. Let me know if you need
any more info. Thanks.
Bryan Phillips - 17 Jan 2007 03:17 GMT
I have not been able to produce the error.  Here is my code:

------------------------------------------------------------------
   public class ACComboBox : System.Windows.Forms.ComboBox {
       public ACComboBox() : base() {
       }

       protected override void
OnKeyPress(System.Windows.Forms.KeyPressEventArgs e) {
           DroppedDown = true;

           if (char.IsControl(e.KeyChar))
               return;

           string ToFind = Text.Substring(0, SelectionStart) +
e.KeyChar; int Index = FindStringExact(ToFind);
           if (Index == -1)
               Index = FindString(ToFind);

           if (Index == -1)
               return;

           SelectedIndex = Index;
           SelectionStart = ToFind.Length;
           SelectionLength = Text.Length - SelectionStart;
           e.Handled = true;
           base.OnKeyPress(e);
       }

       protected override void OnLeave(System.EventArgs e) {
           string text = Text;
           int index = FindStringExact(text, -1);
           if (index < 0)
               index = 0;

           SelectedIndex = index;
           base.OnLeave(e);
       }
}
------------------------------------------------------------------

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

       private void Form1_Load(object sender, EventArgs e) {
           ArrayList types = new ArrayList();
           foreach (Type t in
this.GetType().BaseType.Assembly.GetTypes()) {
               types.Add(t.Name);
           }

           types.Sort();

           foreach (string type in types) {
               acComboBox1.Items.Add(type);
           }
       }

       private void button1_Click(object sender, EventArgs e) {
           MessageBox.Show(acComboBox1.SelectedItem.ToString());
       }
   }

--------------------------------------------------------------------------------------

   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.button1 = new System.Windows.Forms.Button();
           this.acComboBox1 = new
MSDN_AutoCompleteDropDown.ACComboBox();
           this.textBox1 = new System.Windows.Forms.TextBox();
           this.SuspendLayout();
           //
           // button1
           //
           this.button1.Location = new System.Drawing.Point(458, 64);
           this.button1.Name = "button1";
           this.button1.Size = new System.Drawing.Size(75, 23);
           this.button1.TabIndex = 2;
           this.button1.Text = "button1";
           this.button1.Click += new
System.EventHandler(this.button1_Click);
           //
           // acComboBox1
           //
           this.acComboBox1.Location = new System.Drawing.Point(40,
63);
           this.acComboBox1.Name = "acComboBox1";
           this.acComboBox1.Size = new System.Drawing.Size(412, 24);
           this.acComboBox1.TabIndex = 1;
           //
           // textBox1
           //
           this.textBox1.Location = new System.Drawing.Point(40, 35);
           this.textBox1.Name = "textBox1";
           this.textBox1.Size = new System.Drawing.Size(100, 22);
           this.textBox1.TabIndex = 0;
           //
           // Form1
           //
           this.ClientSize = new System.Drawing.Size(772, 257);
           this.Controls.Add(this.textBox1);
           this.Controls.Add(this.button1);
           this.Controls.Add(this.acComboBox1);
           this.Name = "Form1";
           this.Text = "Form1";
           this.Load += new System.EventHandler(this.Form1_Load);
           this.ResumeLayout(false);
           this.PerformLayout();

       }

       #endregion

       private ACComboBox acComboBox1;
       private System.Windows.Forms.Button button1;
       private System.Windows.Forms.TextBox textBox1;
   }

--
Bryan Phillips
MCSD, MCDBA, MCSE
Blog:  http://bphillips76.spaces.live.com

> Hi Bryan
>
[quoted text clipped - 16 lines]
> Hope my expanation makes more sense this time. Let me know if you need
> any more info. Thanks.
aferriere - 17 Jan 2007 17:42 GMT
Hi Bryan

The problem occurs only when you use a DataBound combobox. Like I
mentioned in my post earlier I am binding the combobox to the fname
field of the employee table from pubs database. You can obviously bind
it to any DB which you prefer.
aferriere - 17 Jan 2007 19:07 GMT
Bryan heres the code for the form which I am using to test. The code
for ACComboBox stays the same.
Please change the ConnectionString to point to your pubs DB

using System;
using System.Drawing;
using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace WindowsApplication1
{
    /// <summary>
    /// Summary description for Form3.
    /// </summary>
    public class Form3 : System.Windows.Forms.Form
    {
        private WindowsApplication1.ACComboBox comboBox4;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form3()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if(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.comboBox4 = new WindowsApplication1.ACComboBox();
            this.button1 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            //
            // comboBox4
            //
            this.comboBox4.Location = new System.Drawing.Point(8, 8);
            this.comboBox4.Name = "comboBox4";
            this.comboBox4.Size = new System.Drawing.Size(121, 21);
            this.comboBox4.TabIndex = 2;
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(8, 80);
            this.button1.Name = "button1";
            this.button1.TabIndex = 3;
            this.button1.Text = "button1";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // label1
            //
            this.label1.Location = new System.Drawing.Point(8, 40);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(280, 32);
            this.label1.TabIndex = 4;
            this.label1.Text = "label1";
            //
            // Form3
            //
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(292, 273);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.comboBox4);
            this.Controls.Add(this.button1);
            this.Name = "Form3";
            this.Text = "Form3";
            this.Load += new System.EventHandler(this.Form3_Load);
            this.ResumeLayout(false);

        }
        #endregion

        private void Form3_Load(object sender, System.EventArgs e)
        {
            loadCombo();
        }
        private void loadCombo()
        {
            DataSet ds=new DataSet();
            using(SqlConnection con=new SqlConnection("YOUR CONNECTION STRING"))
            {
                SqlCommand cmd=new SqlCommand("SELECT DISTINCT fname, emp_id FROM
employee ORDER BY fname",con);
                SqlDataAdapter da=new SqlDataAdapter(cmd);
                da.Fill(ds);
            }
            this.comboBox4.DataSource=ds.Tables[0];
            this.comboBox4.DisplayMember="fname";
            this.comboBox4.ValueMember="emp_id";
            this.comboBox4.SelectedIndex=0;
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            string text="SelectedText="+this.comboBox4.Text+"\n Selected
Index="+this.comboBox4.SelectedIndex;
            this.label1.Text=text;
        }

    }
}
aferriere - 17 Jan 2007 19:58 GMT
Bryan I just noticed that you were using .NET 2.0 to Test. I was using
.NET 1.1. I just tested the code on 2.0 and everything works fine.
There is definitely a bug when I use .NET 1.1 and a DataBound ComboBox.
Can you check your code on .NET 1.1 using a DataBound ComboBox and let
me know what you find. Thanks
Bryan Phillips - 18 Jan 2007 02:47 GMT
I compiled using version 1.1 of csc and still could not produce the
problem.  What exactly are you binding to?

--
Bryan Phillips
MCSD, MCDBA, MCSE
Blog:  http://bphillips76.spaces.live.com

> Bryan I just noticed that you were using .NET 2.0 to Test. I was using
> .NET 1.1. I just tested the code on 2.0 and everything works fine.
> There is definitely a bug when I use .NET 1.1 and a DataBound ComboBox.
> Can you check your code on .NET 1.1 using a DataBound ComboBox and let
> me know what you find. Thanks
aferriere - 18 Jan 2007 20:33 GMT
I am binding the combobox to the fname field of the employee table from
pubs database. You can obviously bind
it to any DB which you prefer.

The way to recreat the problem is that you have to use your keyboard
only when you are selecting items in the combobox. when you use the
mouse things work fine. So for eg: use your TAB key to get to the
combobox. Then for eg type any letter lets say 'M' the combox selected
text changes to the first Name which starts with 'M' and then Tab out
again to the button. Click the button now on the code behind the
combobox SelectedIndex, etc.. point to previously selected item. Also
if you use your arrow keys to choose the combobox items things work
fine. So you have to just use the letter keys to select an item and
then tab out to the button to reproduce the error.
Brian Gibbons - 24 Jan 2007 22:43 GMT
We've been fighting with exactly the same problem for quite a while. I
was happy to see that it wasn't just us and the way we are doing things
(subclassed the ctrl but still used as a bound control).  I believe I
have found a solution (read hack) that gets around the problem.  It all
hinges on the dropdown.  If you programmatically change the DroppedDown
property to false as you are leaving the control (likely through the
validate event or possibly the lostfocus) you will notice that you will
get the previous value as you are encountering using the I/F.  My sleazy
hack is to capture the SelectedIndex and reset it after closing up the
drop down.

Note that you must get to the values before the dropdown list closes 'by
itself'.

If lstCollection.DroppedDown Then
  Dim x As Int32 = lstCollection.SelectedIndex
  lstCollection.DroppedDown = False
  lstCollection.SelectedIndex = x
End If

Apologies for assaulting your ocular ports with the VB code.
aferriere - 26 Jan 2007 21:30 GMT
Hi Brian

Thanks for the post. I should have posted my solution earlier. After
hours of struggling with this thing I finally stumbled on the solution.
Here is the working code for the ComboBox class. In the OnLeave event I
set DroppedDown to false and that fixes the issue. Hope this helps
someone who is struggling with this bug.

public class ACComboBox : System.Windows.Forms.ComboBox {
       public ACComboBox() : base() {
       }

       protected override void
OnKeyPress(System.Windows.Forms.KeyPressEventArgs e) {

           if (char.IsControl(e.KeyChar))
               return;

           string ToFind = Text.Substring(0, SelectionStart) +
e.KeyChar; int Index = FindStringExact(ToFind);
           if (Index == -1)
               Index = FindString(ToFind);

           if (Index == -1)
               return;

           DroppedDown = true;
           SelectedIndex = Index;
           SelectionStart = ToFind.Length;
           SelectionLength = Text.Length - SelectionStart;
           e.Handled = true;
           base.OnKeyPress(e);
       }

       protected override void OnLeave(System.EventArgs e) {
           string text = Text;
           int index = FindStringExact(text, -1);
           if (index < 0)
               index = 0;

           if(DroppedDown)
    DroppedDown=false;

           SelectedIndex = index;
           base.OnLeave(e);
       }

}

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.