Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how to set what a combobox displays in the textbox area

Status
Not open for further replies.

Akourou

Programmer
Mar 28, 2019
34
GR
hello,

I have a combobox that is used to select a guest from a table of guests

some of the properties of the combo:
boundcolumn=.3
boundto=.t.
rowsource = guest.last, first, g_no
rowsourcetype = 6 fields

the combo works fine

my problem is that when i select from the dropdown list then in the textbox portion of the combo only lastname is displayed.
is there a way to display both last and first?

 
Yes. First, set [tt].ColumnCount[/tt] to 2. That will display the first two columns (guest.last and guest.first, in this case).

The problem is that the columns will be "ragged", which is the result of using proportional fonts. (If you don't understand the reason for this, just try it for yourself.) To cure that, you could use a fixed-pitch font such as Courier New, but most people consider that ugly.

An alternative solution is to set the colum widths to specific values. To do that, set [tt].ColumnWidth[/tt] to a comma-delimited list of the desired values. For example, [tt].ColumnWidth = "30,25"[/tt]. You will have to experiment to get the best values for your data.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
The textbox portion is always displaying the first field only, so make that an expression you need. You can't only use pure fields with rowsourcetype fields.

If you go for the northwind employees table with lastname, firstname, employeeid - you can set a combobox to this

[pre]BoundColumn = 4
ColumnCount = 4
ColumnWidths = "0,100,100,0" && what columns you see in the expanded items list from which you pick
RowSourceType = 6
RowSource = "lastname-(', '+firstname), lastname, firstname, employeeid"
ControlSource = "employees"
Width = 200
BoundTo = .T.[/pre]

Collapsed, a combobox always displays column 1 of the fields, so to show the full name that's the expression [tt]lastname-(', '+firstname)[/tt]. If you don't know what minus does in string concatenation look it up in the help. In short, this results in displaying "Lastname, Firstname"

In the expanded items list, the columnwidth property determines which width the columns listed have. You could also just show Column 1 there, but a better layout is the two separated name part columns - each in its own left-aligned column. That's columns 2 and 3, thus you don't want to see column 1 (the lastname,firstname epression) and column 4 (the employeeid number) and use columnwidths="0,100,100,0" to make columns 1 and 4 disappear in the item list.

I don't know from the top of my head how you can get the dropdown list width right. In my tests, the dropdown list width didn't align with the combobox width, but that should be possible.

Chriss
 
Oops. Sorry, I didn't read your question carefully. I thought you wanted to display both parts of the name in the drop-down portion. In fact, you want them to appear in the textbox portion.

No, as far as I know that's not possible. The best I can suggest is that you combine the two fields into a single field, and use that as your RowSource. But that is probably now what you want.

I'll leave my previous answer in place for the benefit of anyone who wants to know how to display multiple columns in the drop-down portion of a combo.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi
You may want to have a look at DISPLAYVALUE (see code below)

Code:
PUBLIC oForm1

oform1=NEWOBJECT("form1")
oForm1.Visible = .T.
oform1.Show

READ Events

CLOSE ALL
CLEAR ALL 

RETURN

**********

DEFINE CLASS form1 AS form
Height = 240
Width = 360
Autocenter = .T.
Borderstyle = 2
MinButton = .F.
MaxButton = .F.
Themes = .F.
ShowTips = .T.

	ADD OBJECT cboChooseGuest as ComboBox WITH ;
		Style = 0, ;
		Top = 60, ;
		Left = 12, ;
		Width = 300, ;
		RowSourceType = 6, ;
		RowSource = "Guests.LastName, FirstName, G_No", ;
		BoundTo = .T., ;
		BoundColumn = 3, ;
		ColumnCount = 3, ;
		ColumnWidths = "120, 120, 30, 0"
		
	[highlight #8AE234]	PROCEDURE cboChooseGuest.InterActiveChange()
			WITH This
				.DisplayValue = ALLTRIM(This.List[This.ListIndex, 1]) + " - " + ALLTRIM(This.List[This.Listindex, 2]) + " - " + ALLTRIM(This.List[This.Listindex, 3])
				.Refresh()
			ENDWITH 
		ENDPROC
[/highlight]
	PROCEDURE Load
		CREATE CURSOR Guests (LastName C(48), FirstName C(48), G_No C(3))
		INSERT INTO Guests values("Meyer", "Goerge", "1")
		INSERT INTO Guests values("Bogart", "Humphrey", "2")
		INSERT INTO Guests values("Hepburn", "Katherine", "3")
		INSERT INTO Guests values("Cluny", "Goerge", "4")
ENDPROC

	PROCEDURE Destroy
		CLEAR EVENTS

	ENDPROC 

ENDDEFINE

**********

hth

MarK



 
I won't decide what's better, not because I'm biased towards my solution. In both cases you need to compute what you want to be displayed. In MarKs solution the fields rowsourecetype keeps at just being fields but you need code in an event in my case the rowsource expression is interpreting the rowsource type "fields" very loosely.

I personally struggle to get MarKs idea working for my combobox in a visual form, it works flawless as his PRG code. But I likely have overlooked a detail to also set correctly. I checked if the key column has to be char and not numeric, but you can also adapt MarKs example to an integer G_No column, though there is something differing with boundto=.t. or .f. comboboxes and integer vs char columns used as boundcolumn. I always forget the reasoning behind that, even when reading the description of boundto in the help. In the end, no matter what the details are, you can get the picked item by knowing it becomes the currently selected record in the rowsource alias.

Chriss
 
actually Criss solution worked fine

and I omitted some columns as they are not needed

BoundColumn = 2
ColumnCount = 2
ColumnWidths = "231,0"
RowSourceType = 6
RowSource = "guest.lastname-(', '+guest.firstname), employeeid"
BoundTo = .T.
ColumnLines = .f.

thank you all for the info

 
...

and a demo with Chriss's suggestion

Code:
PUBLIC oForm1

oform1=NEWOBJECT("form1")
oForm1.Visible = .T.
oform1.Show

READ Events

CLOSE ALL
CLEAR ALL 

RETURN

**********

DEFINE CLASS form1 AS form
Height = 240
Width = 360
Autocenter = .T.
Borderstyle = 2
MinButton = .F.
MaxButton = .F.
Themes = .F.
ShowTips = .T.

	ADD OBJECT lblLName as Label WITH ;
		Top = 24, ;
		Left = 24, ;
		Caption = "Lastname"
	
	ADD OBJECT lblFName as Label WITH ;
		Top = 24, ;
		Left = 24 + 90 + 12, ;
		Caption = "Firstname"
	
	ADD OBJECT lblGNumber as Label WITH ;
		Top = 24, ;
		Left = 24 + 90 + 12 + 90 + 12, ;
		Caption = "Guest"
	
	ADD OBJECT lblRNumber as Label WITH ;
		Top = 24, ;
		Left = 24 + 90 + 12 + 90 + 12 + 60, ;
		Caption = "Room"
	

	ADD OBJECT txtLName as TextBox WITH ;
		Top = 48, ;
		Left = 24, ;
		Width = 90, ;
		ControlSource = "Guests.LastName", ;
		ReadOnly = .T., ;
		DisabledBackColor = RGB(0, 240, 240)

	ADD OBJECT txtFName as TextBox WITH ;
		Top = 48, ;
		Left = 24 + 90 + 12, ;
		Width = 90, ;
		ControlSource = "Guests.FirstName", ;
		ReadOnly = .T., ;
		DisabledBackColor = RGB(0, 240, 240)
		
	ADD OBJECT txtGNumber as TextBox WITH ;
		Top = 48, ;
		Left = 126 + 90 + 12, ;
		Width = 48, ;
		ControlSource = "Guests.G_No", ;
		ReadOnly = .T., ;
		DisabledBackColor = RGB(0, 240, 240)

	ADD OBJECT txtRNumber as TextBox WITH ;
		Top = 48, ;
		Left = 126 + 90 + 12 + 48 + 12, ;
		Width = 48, ;
		Alignment = 1, ;
		ControlSource = "Guests.R_No", ;
		ReadOnly = .T., ;
		DisabledBackColor = RGB(0, 240, 240)
		

[highlight #8AE234]	ADD OBJECT cboChooseGuest as ComboBox WITH ;
		Style = 2, ;
		Top = 90, ;
		Left = 24, ;
		Width = 312, ;
		BoundColumn = 4, ;
		ColumnCount = 4, ;
		ColumnWidths = "0,138,138,0", ;
		RowSourceType = 6, ;
		RowSource = "Guests.lastname-(', '+firstname-(', ' + ALLTRIM(STR(G_No)))), lastname, firstname, G_No", ;
		ControlSource = "Guests", ;
		BoundTo = .T. 
		IncrementalSearch = .T.

		PROCEDURE cboChooseGuest.Click()
			ThisForm.txtLName.SetFocus()
			Thisform.Refresh()

		ENDPROC[/highlight] 

	PROCEDURE Load
		CREATE CURSOR Guests (LastName C(48), FirstName C(48), G_No I , R_No C(3))
		
		INSERT INTO Guests values("Meyer", "Jeffrey", 1, "15")
		INSERT INTO Guests values("Bogart", "Humphrey", 22, "17")
		INSERT INTO Guests values("Hepburn", "Katherine", 3, "223")
		INSERT INTO Guests values("Clooney", "Goerge", 4, "545")
		INSERT INTO Guests values("Miller", "Chris", 5, "54")
		INSERT INTO Guests values("Lewis", "Mike", 26, "11")
		INSERT INTO Guests values("Fisher", "Jenny", 16, "121")
		
		LOCATE 

	ENDPROC 

	PROCEDURE Destroy
		CLEAR EVENTS

	ENDPROC 

ENDDEFINE

**********
 
Hi Chris

Chriss said:
I checked if the key column has to be char and not numeric, ...

Does not seems to be crucial anymore - at least if you work with VFP 9

from Hacker's Guide to VFP 7

The behavior of lists and combos with numeric data confuses people. The key point is that, even when we think we're seeing numbers in a combo or list, we're actually seeing characters. Combos and lists cannot show numeric data. If you specify a RowSource that's numeric, FoxPro internally converts the data to character before displaying it.

The Value of a list or combo (and, therefore, the ControlSource it's bound to) can be either character or numeric. If the Value is character, it contains the text of the currently highlighted item. If the Value is numeric, by default it contains the index of that item. Before VFP 5, there was no way to get numeric data out of a list or combo. The BoundTo property lets you tell VFP to convert a numeric character string to a number before sticking it into Value or DisplayValue.

hth

MarK
 
I know Hacker's guide is usually enlightening in such things.

But take this:
Hacker's guide said:
The BoundTo property lets you tell VFP to convert a numeric character string to a number before sticking it into Value or DisplayValue.
I see the value becoming the string of an integer id, no matter if I set boundto=.T. or .F.

It's not more than an annoyance as you can always read the actual numeric ID from the table you bound to the combobox, there never is much value in the value of a control anyway, if you bind it to something, you know the source of that value and the source has the original value, so once you use bound controls the controls are only there for diplaying things to the user and the user will not be able to distinguish a string of a number to a number, as a binary nummber also when sticking to the datatype number when bound to, say, a textbox, is always cconverted from the bytes it is to a string of a number. there are just slight hints in case of a textbox, for example, whether the number is aligned right or not.

The essence off what I keep in mind is as long as you get controls to show what you want them to show and to update the tables they're bound to as you want, the goal is achieved and I'd then always read my data from the data - from the tables - not from a control.value anyway. So I'll not be affected by this.

The boundto of a combobox becomes more important, if you also use the combobox.controlsource and the picked item from the rowsource sets the controlsource. In a normalized design you want the primary key of a list of items you display for selection to be stored into a foreign key field, while displayvalue should be something that correspoonds to the key, like a fullname of a person, a productname or anything the key stands for. That's the "holy grail" usage of a combobox, perhaps, editing a foreign key field without the user to need to make the translation from keys to what they stand for.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top