Click here to Skip to main content
15,891,136 members
Articles / Mobile Apps

Editable History ComboBox

Rate me:
Please Sign up or sign in to vote.
4.68/5 (20 votes)
11 Feb 2004CPOL1 min read 92.8K   761   39   4
Demonstrates how to easily simulate an editable combobox that can persist previous entries (Like Internet Explorer).

Sample Image - historycombo.jpg

Introduction

The Compact Framework does not provide the option for an editable combobox, but there is an easy way to work around this limitation. The following article will explain how to create an editable combobox that remembers up to 10 previous entries (Like the address bar in Internet Explorer).

Using the code

To make a combobox editable, you simply overlay a text box on a combobox.  To make the textbox and combobox fit together seamlessly you can just add code to each combobox like so:

C#
int dropDownButtonWidth = 14;
txtTest1.Bounds = cboTest1.Bounds;
txtTest1.Width -= dropDownButtonWidth;

Now, to complete the behavior of the editable combobox, you just need to make sure the textbox gets updated with the currently selected item from the combobox.  Refer to the code below:

C#
private void cboTest1_SelectedIndexChanged(object sender, System.EventArgs e)
{
    txtTest1.Text = cboTest1.Text;
}

This is all you need to do to get the behavior of an editable combobox.  If you would like to create a history combobox, you will need an XML file to persist the combobox entries. The code to load the past entries is pretty straightforward.

C#
// Load the combobox entries from the XML file.
xdoc.Load(@"\Path to comboboxes.xml");
XmlElement root = xdoc.DocumentElement;
XmlNodeList nodeList = root.ChildNodes;
ComboBox cboHistory;

for(int j=0; j<nodeList.Item(i).ChildNodes.Count; ++j)
{
    cboHistory.Items.Add(nodeList.Item(i).ChildNodes.Item(j).InnerText);    
}
The code to save new entries is a little more involved but not too bad.
C#
int maxEntriesToStore = 10;
XmlTextWriter tw = new XmlTextWriter(@"\Path to comboboxes.xml", 
                                     System.Text.Encoding.UTF8);
tw.WriteStartDocument();
tw.WriteStartElement("comboboxes");
tw.WriteStartElement("combobox");
tw.WriteStartAttribute("name", string.Empty);
tw.WriteString("cboTest1");
tw.WriteEndAttribute();

// Write the item from the text box first.
if(txtTest1.Text.Length != 0)
{
    tw.WriteStartElement("entry");
    tw.WriteString(txtTest1.Text);
    tw.WriteEndElement();
    maxEntriesToStore -= 1;
}

// Write the rest of the entries (up to 10).
for(int i=0; i < cboTest1.Items.Count && i < maxEntriesToStore; ++i)
{
    if(txtTest1.Text != cboTest1.Items[i].ToString())
    {
        tw.WriteStartElement("entry");
        tw.WriteString(cboTest1.Items[i].ToString());
        tw.WriteEndElement();
    }
}

tw.WriteEndElement();
tw.WriteEndElement();
tw.Flush();
tw.Close();
The demo project contains code to handle 3 comboboxes and is arranged a little differently than the sample code above. Enjoy! Smile | :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Check out my blog! http://www.pagebrooks.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey27-Mar-12 23:48
professionalManoj Kumar Choubey27-Mar-12 23:48 
GeneralSample ComboBox code for .net CF Pin
Kalzon13-Feb-05 14:31
Kalzon13-Feb-05 14:31 
Thanks for the article. I took it and went ahead and created a derived class. The following is the code I put together to do some of the missing .net CF functions. I hope this helps save some people some time.


using System;

namespace KAL.Handheld.Controls
{
///
/// Editable ComboBox.
///

public class ComboBox: System.Windows.Forms.Control
{
private KAL.HTrakkerStand.Controls.TextBox tb = new KAL.HTrakkerStand.Controls.TextBox();
private System.Windows.Forms.ComboBox cb = new System.Windows.Forms.ComboBox();

private int c_intTabIndex = 0;
private String c_strName ="";
private bool c_blnUpdatingValue= false;

public event System.EventHandler SelectedIndexChanged;

public event EventHandler EnterHit;

public ComboBox()
{
//Load the textbox and comboBox and add them to this control
tb.Show();
this.Controls.Add(tb);
cb.Show();
this.Controls.Add(cb);
tb.BringToFront();

cb.SelectedValueChanged +=new EventHandler(cb_SelectedValueChanged);
cb.SelectedIndexChanged +=new EventHandler(cb_SelectedIndexChanged);

tb.LostFocus += new EventHandler(tb_TextChanged);

tb.KeyUp +=new System.Windows.Forms.KeyEventHandler(ComboBox_KeyUp);
}

///
/// Gets or sets the Width of the control
///

public new int Width
{
get
{
return base.Width;
}
set
{
//set the width of the textbox and combo box
base.Width=value;
tb.Width=base.Width-19; //- the Drop Down Size
cb.Width=base.Width;
}
}

///
/// Gets or sets the Height of the control
///

public new int Height
{
get
{
return base.Height;
}
set
{
//set the height of the textbox and combo box
base.Height=value;
tb.Height=base.Height;
cb.Height=base.Height;
}
}

public new System.Drawing.Size Size
{
get
{
return base.Size;
}
set
{
base.Size= value;
this.Height= base.Height;
this.Width= base.Width;
}
}

///
/// Gets or sets the Background color of the control
///

public new System.Drawing.Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
tb.BackColor=base.BackColor;
cb.BackColor=base.BackColor;
}
}

///
/// Gets or sets the name of the control
///

public String Name
{
get
{
return c_strName;
}
set
{
c_strName = value;
}
}

///
/// Gets or sets the text associated with the control
///

public new string Text
{
get
{
return tb.Text;
}
set
{
cb.Text=value;
}
}

public new bool Focus()
{
return tb.Focus();
}

public int TabIndex
{
get
{
return c_intTabIndex;
}
set
{
c_intTabIndex = value;
}
}

///
/// Gets an object representing the collection of the objects contained
/// in this comboBox
///

public System.Windows.Forms.ComboBox.ObjectCollection Items
{
get
{
return cb.Items;
}
}

///
/// Gets or set the value of the member property specified by the
/// System.Windows.Forms.ListControl.ValueMember property
///

public object SelectedValue
{
get
{
return cb.SelectedValue;
}
set
{
cb.SelectedValue=value;
//this is used because the cb.SelectedValue change does not get triggered
//from here for some reason.
cb.Refresh();
tb.Text=cb.Text;
}
}

///
/// Gets or sets the dataSource for the System.Windows.Forms.ListControl
///

public object DataSource
{
get
{
return cb.DataSource;
}
set
{
cb.DataSource=value;
}
}

///
/// Gets the dataBindings for the control
///

public new System.Windows.Forms.ControlBindingsCollection DataBindings
{
get
{
return cb.DataBindings;
}
}

///
/// Gets or sets the string the specifies the property of the datasource
/// whose contents you want to display
///

public String DisplayMember
{
get
{
return cb.DisplayMember;
}
set
{
cb.DisplayMember=value;
}
}

///
/// Gets or sets the index specifing the selected item.
///

public int SelectedIndex
{
get
{
return cb.SelectedIndex;
}
set
{
cb.SelectedIndex = value;
}
}

///
/// Gets or sets a string the specifies the property of the datasource
/// from which to draw the value.
///

public string ValueMember
{
get
{
return cb.ValueMember;
}
set
{
cb.ValueMember= value;
}
}

public int FindStringExact(String strText)
{
try
{
for (int i=0; i< cb.Items.Count; i++)
{
if (strText == cb.GetItemText(cb.Items[i]))
{
return i;
}
}
}
catch (Exception ex)
{
throw new System.Exception("Error finding String. KAL.Handheld.Controls.ComboBox.FindExact",ex);
}
throw new System.Exception("Entry not found in drop down");
}

///
/// when the ComboBox is changed, change the textbox text to reflect the
/// text.
///

/// <param name="sender" />
/// <param name="e" />
private void cb_SelectedValueChanged(object sender, EventArgs e)
{
try
{
//So that does not cause endless loop of updating
if (this.c_blnUpdatingValue ==false)
{
this.c_blnUpdatingValue=true;
tb.Text=cb.Text;
this.c_blnUpdatingValue=false;
}
}
catch{}
}

///
/// send notice of change
///

/// <param name="sender" />
/// <param name="e" />
private void cb_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
this.SelectedIndexChanged(this,e);
}
catch//This is used in case there is nothing listening for this change
{
}
}

///
/// set the comboBox value to this value
///

/// <param name="sender" />
/// <param name="e" />
private void tb_TextChanged(object sender, EventArgs e)
{
try
{
//So that does not cause endless loop of updating
if (this.c_blnUpdatingValue ==false)
{
this.c_blnUpdatingValue=true;
cb.Text = tb.Text;
this.c_blnUpdatingValue=false;
}
}
catch
{}
}

private void ComboBox_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
try
{
if (e.KeyCode == System.Windows.Forms.Keys.Enter)
{
this.Focus();
EnterHit(this,e);
}
}
catch{}//This is used in case there is nothing listening for this event
}
}
}


Keith Longwell
http://www.KalzoneInc.com
GeneralNice Article Pin
jadeboy12-Feb-04 16:55
jadeboy12-Feb-04 16:55 
GeneralRe: Nice Article Pin
pbrooks12-Feb-04 17:09
pbrooks12-Feb-04 17:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.