Solved

ListView with combobox

Posted on 2009-07-16
6
2,625 Views
Last Modified: 2012-05-07
I have managed to create everything but I am still missing how to add a combobox to my listview
Please show me how to do this.

I have been to alot of webpages and I cant seem to get it running. So I dont need links to webpages. I do need someone to show how to do it.

My combobox name is teleComboBox
in my Contact class is all the phones I want to add int this: private List<Phone> m_phone;
listView1.Clear();
 
            // Used for creating listview items.
            ListViewItem listviewitem;
 
            //ListViewItem subItem = new ListViewItem();
            listView1.Columns.Add("FirstName");
            listView1.Columns.Add("LastName");
            listView1.Columns.Add("E-mail");
            listView1.Columns.Add("Phonenumbers");
 
            // Ensure that the view is set to show details.
            listView1.View = View.Details;
            listView1.FullRowSelect = true;
 
            // Create some listview items consisting of first and last names.
            foreach (Contact contact in contactManager.Contacts)
            {
                listviewitem = new ListViewItem(contact.FirstName);
                listviewitem.SubItems.Add(contact.LastName);
                listviewitem.SubItems.Add(contact.MyEmail.Personal);
 
                //listviewitem.SubItems.Add(contact.Telephone.ToString());
 
                this.listView1.Items.Add(listviewitem);
 
 
            }

Open in new window

0
Comment
Question by:Mickeys
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 
LVL 13

Expert Comment

by:drypz
ID: 24867309
hi! you may refer to this link

http://support.microsoft.com/kb/320344
0
 

Author Comment

by:Mickeys
ID: 24867401
been there. Didnt get it to work. So please...no more links. Just show me how to do it.
0
 
LVL 29

Expert Comment

by:Gautham Janardhan
ID: 24867444
are u using WPF ?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Mickeys
ID: 24867470
I have no idea. I have created a windows form....am I using it then? (VS2008)
0
 
LVL 8

Expert Comment

by:rambovn
ID: 24867608
just follow the link http://support.microsoft.com/kb/320344 and post your problem here
It is a good tutorial.
0
 
LVL 29

Accepted Solution

by:
Gautham Janardhan earned 500 total points
ID: 24867704

/* ListViewEx.cs 
 * This file contains the definition of the class ListViewEx, which is a
 * reusable class derived from ListView. 
*/
 
#region Namespaces
using System;
using System.Drawing;
using System.Collections;
using System.Diagnostics;
using System.Windows.Forms;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
#endregion
 
namespace CustomListView
{
	/// <summary>
	/// Class derived from ListView to give ability to display controls
	/// like TextBox and Combobox
	/// </summary>
	public class ListViewEx : ListView
	{
		#region The RECT structure
		/// <summary>
		/// This struct type will be used as the oupput 
		/// param of the SendMessage( GetSubItemRect ). 
		/// Actually it is a representation for the strucure 
		/// RECT in Win32
		/// </summary>
		[StructLayout(LayoutKind.Sequential)]
		internal struct RECT
		{
			public int left;
			public int top;
			public int right;
			public int bottom;
		}
		#endregion
 
		#region Win32 Class
		/// <summary>
		/// Summary description for Win32.
		/// </summary>
		internal class Win32
		{
			/// <summary>
			/// This is the number of the message for getting the sub item rect.
			/// </summary>
			public const int LVM_GETSUBITEMRECT  = (0x1000) + 56;
 
			/// <summary>
			/// As we are using the detailed view for the list,
			/// LVIR_BOUNDS is the best parameters for RECT's 'left' member.
			/// </summary>
			public const int LVIR_BOUNDS = 0;
 
			/// <summary>
			/// Sending message to Win32
			/// </summary>
			/// <param name="hWnd">Handle to the control</param>
			/// <param name="messageID">ID of the message</param>
			/// <param name="wParam"></param>
			/// <param name="lParam"></param>
			/// <returns></returns>
			[DllImport("user32.dll", SetLastError=true)]
			public static extern int SendMessage(IntPtr hWnd, int messageID, int wParam , ref RECT lParam);
		}
		#endregion
 
		#region SubItem Class
		/// <summary>
		/// This class is used to represent 
		/// a listview subitem.
		/// </summary>
		internal class SubItem
		{
			/// <summary>
			/// Item index
			/// </summary>
			public readonly int row;
 
			/// <summary>
			/// Subitem index
			/// </summary>
			public readonly int col;
 
			/// <summary>
			/// Parameterized contructor
			/// </summary>
			/// <param name="row"></param>
			/// <param name="col"></param>
			public SubItem( int row, int col )
			{
				this.row = row;
				this.col = col;
			}
		}
		#endregion
 
		#region Variables & Properties
		/// <summary>
		/// If this variable is true, then 
		/// subitems for an item is added 
		/// automatically, if not present.
		/// </summary>
		private bool addSubItem = false;
		public bool AddSubItem 
		{
			set
			{
				this.addSubItem = value;
			}
		}
 
		/// <summary>
		/// This variable tells whether the combo box 
		/// is needed to be displayed after its selection
		/// is changed
		/// </summary>
		private bool hideComboAfterSelChange = false;
		public bool HideComboAfterSelChange
		{
			set
			{
				this.hideComboAfterSelChange = value;
			}
		}
 
		/// <summary>
		/// Represents current row
		/// </summary>
		private int row = -1;
 
		/// <summary>
		/// Represents current column
		/// </summary>
		private int col = -1;
 
		/// <summary>
		/// Textbox to display in the editable cells
		/// </summary>
		private TextBox textBox = new TextBox();
 
		/// <summary>
		/// Combo box to display in the associated cells
		/// </summary>
		private ComboBox combo = new ComboBox();
 
		/// <summary>
		/// This is a flag variable. This is used to determine whether
		/// Mousebutton is pressed within the listview
		/// </summary>
		private bool mouseDown = false;
 
		/// <summary>
		/// To store, subitems that contains comboboxes and text boxes
		/// </summary>
		private Hashtable customCells = new Hashtable();
		#endregion
 
		#region Methods
		/// <summary>
		/// Constructor
		/// </summary>
		public ListViewEx()
		{
			// Initialize controls
			this.InitializeComponent();
		}
 
		/// <summary>
		/// Initializes the text box and combo box
		/// </summary>
		private void InitializeComponent()
		{
			// Text box
			this.textBox.Visible = false;
			textBox.BorderStyle = BorderStyle.FixedSingle;
			this.textBox.Leave += new EventHandler(textBox_Leave);
 
			// Combo box
			this.combo.Visible = false;
			this.Controls.Add( this.textBox );
			this.Controls.Add( this.combo );
			this.combo.DropDownStyle = ComboBoxStyle.DropDownList;
			this.combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
		}
 
		/// <summary>
		/// This method will send LVM_GETSUBITEMRECT message to 
		/// get the current subitem bouds of the listview
		/// </summary>
		/// <param name="clickPoint"></param>
		/// <returns></returns>
		private RECT GetSubItemRect(Point clickPoint)
		{
			// Create output param
			RECT subItemRect = new RECT();
 
			// Reset the indices
			this.row = this.col = -1;
			
			// Check whether there is any item at the mouse point
			ListViewItem item = this.GetItemAt(clickPoint.X, clickPoint.Y);
 
			if(item != null )
			{
				for(int index = 0; index < this.Columns.Count; index++)
				{				
					// We need to pass the 1 based index of the subitem.
					subItemRect.top = index + 1; 
 
					// To get the boudning rectangle, as we are using the report view
					subItemRect.left = Win32.LVIR_BOUNDS;
					try
					{
						// Send Win32 message for getting the subitem rect. 
						// result = 0 means error occuured
						int result = Win32.SendMessage(this.Handle, Win32.LVM_GETSUBITEMRECT, item.Index, ref subItemRect);
						if( result != 0 )
						{
							// This case happens when items in the first columnis selected.
							// So we need to set the column number explicitly
							if(clickPoint.X < subItemRect.left)
							{
								this.row = item.Index;
								this.col= 0;
								break;
							}
							if(clickPoint.X >= subItemRect.left & clickPoint.X <= 
								subItemRect.right)
							{
								this.row = item.Index;
								// Add 1 because of the presence of above condition
								this.col = index + 1;
								break;
							}
						}
						else
						{
							// This call will create a new Win32Exception with the last Win32 Error.
							throw new Win32Exception();
						}
					}
					catch( Win32Exception ex )
					{
						Trace.WriteLine( string.Format("Exception while getting subitem rect, {0}", ex.Message ));
					}
				}
			}			
			return subItemRect;
		}
 
		/// <summary>
		/// Set a text box in a cell
		/// </summary>
		/// <param name="row">The 0-based index of the item.  Give -1 if you
		///					  want to set a text box for every items for a
		///					  given "col" variable.
		///	</param>
		/// <param name="col">The 0-based index of the column. Give -1 if you
		///					  want to set a text box for every subitems for a
		///					  given "row" variable.
		///	</param>
		public void AddEditableCell( int row, int col )
		{
			// Add the cell into the hashtable
			// Value is setting as null because it is an editable cell
			this.customCells[new SubItem( row, col )] = null;
		}
 
		/// <summary>
		/// Set a combobox in a cell
		/// </summary>
		/// <param name="row"> The 0-based index of the item.  Give -1 if you
		///					   want to set a combo box for every items for a
		///					   given "col" variable.
		///	</param>
		/// <param name="col"> The 0-based index of the column. Give -1 if you
		///					   want to set a combo box for every subitems for a
		///					   given "row" variable.
		///	</param>
		/// <param name="data"> Items of the combobox 
		/// </param>
		public void AddComboBoxCell( int row, int col, StringCollection data )
		{
			// Add the cell into the hashtable
			// Value for the hashtable is the combobox items
			this.customCells[new SubItem( row, col )] = data;
		}
 
		/// <summary>
		/// Set a combobox in a cell
		/// </summary>
		/// <param name="row"> The 0-based index of the item.  Give -1 if you
		///					   want to set a combo box for every items for a
		///					   given "col" variable.
		///	</param>
		/// <param name="col"> The 0-based index of the column. Give -1 if you
		///					   want to set a combo box for every subitems for a
		///					   given "row" variable.
		///	</param>
		/// <param name="data"> Items of the combobox 
		/// </param>
		public void AddComboBoxCell( int row, int col, string[] data )
		{
			try
			{
				StringCollection param = new StringCollection();
				param.AddRange( data );
				this.AddComboBoxCell( row, col, param );
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
		}
 
		/// <summary>
		/// This method will display the combobox
		/// </summary>
		/// <param name="location">Location of the combobox</param>
		/// <param name="sz">Size of the combobox</param>
		/// <param name="data">Combobox items</param>
		private void ShowComboBox( Point location, Size sz, StringCollection data )
		{
			try
			{
				// Initialize the combobox
				combo.Size = sz;
				combo.Location = location;
				// Add items
				combo.Items.Clear();
				foreach( string text in data )
				{
					combo.Items.Add( text );
				}			
				// Set the current text, take it from the current listview cell
				combo.Text = this.Items[row].SubItems[col].Text;
				// Calculate and set drop down width
				combo.DropDownWidth = this.GetDropDownWidth(data);
				// Show the combo
				combo.Show();
			}
			catch( ArgumentOutOfRangeException )
			{
				// Sink
			}
		}
 
		/// <summary>
		/// This method will display the textbox
		/// </summary>
		/// <param name="location">Location of the textbox</param>
		/// <param name="sz">Size of the textbox</param>
		private void ShowTextBox( Point location, Size sz )
		{
			try
			{
				// Initialize the textbox
				textBox.Size = sz;
				textBox.Location = location;
				// Set text, take it from the current listview cell
				textBox.Text = this.Items[row].SubItems[col].Text;
				// Shopw the text box
				textBox.Show();
				textBox.Focus();
			}
			catch( ArgumentOutOfRangeException )
			{
				// Sink
			}
		}
 
		/// <summary>
		/// 
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseUp ( MouseEventArgs e)
		{
			try
			{
				// Hide the controls
				this.textBox.Visible = this.combo.Visible = false;
 
				// If no mouse down happned in this listview, 
				// no need to show anything
				if( !mouseDown )
				{
					return;
				}
 
				// The listview should be having the following properties enabled
				// 1. FullRowSelect = true
				// 2. View should be Detail;
				if( !this.FullRowSelect || this.View != View.Details )
				{
					return;
				}
 
				// Reset the mouse down flag
				mouseDown = false;
 
				// Get the subitem rect at the mouse point.
				// Remeber that the current row index and column index will also be
				// Modified within the same method
				RECT rect = this.GetSubItemRect( new Point( e.X, e.Y ));
			
				// If the above method is executed with any error,
				// The row index and column index will be -1;
				if( this.row != -1 && this.col != -1 )
				{
					// Check whether combobox or text box is set for the current cell
					SubItem cell = GetKey(new SubItem(this.row, this.col ));
 
					if( cell != null)
					{
						// Set the size of the control(combobox/editbox)
						// This should be composed of the height of the current items and
						// width of the current column
						Size sz = new Size(this.Columns[col].Width, Items[row].Bounds.Height );
 
						// Determine the location where the control(combobox/editbox) to be placed
						Point location = col == 0 ? new Point(0, rect.top) : new Point( rect.left, rect.top);
					
						ValidateAndAddSubItems();
 
						// Decide which conrol to be displayed.
						if(this.customCells[cell] == null )
						{
							this.ShowTextBox( location, sz );
						}
						else
						{
							this.ShowComboBox( location, sz, (StringCollection) this.customCells[cell] );
						}
					}
				}
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
		}
 
		/// <summary>
		/// 
		/// </summary>
		private void ValidateAndAddSubItems()
		{
			try
			{
				while( this.Items[this.row].SubItems.Count < this.Columns.Count && this.addSubItem )
				{
					this.Items[this.row].SubItems.Add("");
				}
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
		}
 
		/// <summary>
		/// This message will get the largest text from the given
		/// stringarray, and will calculate the width of a control which 
		/// will contain that text.
		/// </summary>
		/// <param name="data"></param>
		/// <returns></returns>
		private int GetDropDownWidth( StringCollection data )
		{
			// If array is empty just return the combo box width
			if( data.Count == 0 )
			{
				return this.combo.Width;
			}
			
			// Set the first text as the largest
			string maximum = data[0];
 
			// Now iterate thru each string, to findout the
			// largest
			foreach( string text in data )
			{
				if( maximum.Length <  text.Length )
				{
					maximum = text;
				}
			}
			// Calculate and return the width .
			return (int)(this.CreateGraphics().MeasureString( maximum , this.Font ).Width);
		}
 
		/// <summary>
		/// For this method, we will get a Subitem. 
		/// Then we will iterate thru each of the keys and will 
		/// check whther any key contains the given cells row/column.
		/// If it is not found we will check for -1 in any one
		/// </summary>
		/// <param name="cell"></param>
		/// <returns></returns>
		private SubItem GetKey( SubItem cell )
		{
			try
			{
				foreach( SubItem key in this.customCells.Keys )
				{
					// Case 1: Any particular cells is  enabled for a control(Textbox/combobox)
					if( key.row == cell.row && key.col == cell.col )
					{
						return key;
					}
						// Case 2: Any particular column is  enabled for a control(Textbox/combobox)
					else if( key.row == -1 && key.col == cell.col )
					{
						return key;
					}
						// Entire col for a row is is  enabled for a control(Textbox/combobox)
					else if( key.row == cell.row && key.col == -1 )
					{
						return key;
					}
						// All cells are enabled for a control(Textbox/combobox)
					else if( key.row == -1 && key.col == -1 )
					{
						return key;
					}
				}
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
			return null;
		}
 
		/// <summary>
		/// 
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseDown(MouseEventArgs e)
		{
			try
			{
				// Mouse down happened inside listview
				mouseDown = true;
 
				// Hide the controls
				this.textBox.Hide();
				this.combo.Hide();
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
		}
 
		/// <summary>
		/// This event handler wll set the current text in the textbox
		/// as the listview's current cell's text, while the textbox 
		/// focus is lost
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void textBox_Leave(object sender, EventArgs e)
		{
			try
			{
				if( this.row != -1 && this.col != -1 )
				{
					this.Items[row].SubItems[col].Text = this.textBox.Text;
					this.textBox.Hide();
				}
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
		}
 
		/// <summary>
		/// This event handler wll set the current text in the combobox
		/// as the listview's current cell's text, while the combobox 
		/// selection is changed
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void combo_SelectedIndexChanged(object sender, EventArgs e)
		{
			try
			{
				if( this.row != -1 && this.col != -1 )
				{
					this.Items[row].SubItems[col].Text = this.combo.Text;
					this.combo.Visible = !this.hideComboAfterSelChange;		
				}
			}
			catch( Exception ex )
			{
				Trace.WriteLine( ex.ToString());
			}
		}
		#endregion
	}
}

Open in new window

0

Featured Post

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

Question has a verified solution.

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

In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
This article introduced a TextBox that supports transparent background.   Introduction TextBox is the most widely used control component in GUI design. Most GUI controls do not support transparent background and more or less do not have the…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

749 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