I think I've stumbled upon a bug in the .NET (or the native windows API) concerning combo boxes.
I'll give a specific scenario:
I have two database tables, with a one to many relation ship between the two, a brief description is as follows:
Table: FinSage
Column Type
SageCode nvarchar(10) (PK)
Desc nvarchar(100)
Table: FinCode
Column Type
FinCode nvarchar(10) (PK)
Desc nvarchar(100)
SageCode nvarchar(10) (FK)
These are entirely user maintained, with only the PK obviously being constrained to be unique. When creating or editing a record on the FinCode table I have a combobox on the screen which has the display member bound to the 'Desc' column and the value member bound to SageCode.
The problem arises when there are duplicate entries in the 'Desc' column, which is quite common under the expected use of the system. It seems the .net combo boxes does a reverse lookup using the display value to get the value member. So when the combo box gains focus it will change the value to the first occurrence of the display member.
I understand that in theory, if there are duplicates in the display value then the combo box effectively has no use as the user doesn't know which value they have selected. However as we know users are not perfect and so they will and do enter the same descriptive value for a code.
I currently get around this by combining the code and the description, however my boss wants them to be able to edit this value by using either the code or the description (as some uses prefer to use one or the other). I tried using two combo boxes bound to the same binding source but saw this problem arise.
Apologies for the verbose description, its not really a problem that can be summed up in code.
On a slightly related note, the combo boxes that Access use don't have this bug. But I believe Access is comparable to WPF in that it draws all its own UI components rather than using the Win32 API.
Is there not a way of 'forcing' a native combo box to find the correct item in the list based on the associated value or was the concept of value-description pair developed after Microsoft designed their native combo box?
Thank you for any insights
Marlon
*edit*
The answer below prompted me to quickly dev up a test application and I'm not getting the same behaviour unless the combobox is inside a datagridview (which is unrelated to the original question).
Sorry Microsoft, I would delete this question but I cant now, ah well, mistakes are good.
The solution is set DropDownList in the DropDownStyle property of the designer
ComboBoxes and ListBoxes do have value-description pairs in the form value(index)-Description(text).
Therefore if the combobox includes to of the same description they are still unique as they don't have the same index.
I'd say rather than there being a bug in .net there's a bug in your code.
Related
I have a DataGridView with several TextBoxColumns and one ComboBox column called 'combo' that holds the client type. The problem is that I'd like to show both the currently selected client-type value along with the dropdown client-type list to validate future changes by the user. In SQL Server, I have a DB with two table columns, 'client_type_dropdown.name' and 'clients.client_type'. The 'client_type_dropdown.name' column is a validation list. The 'clients.client_type' column contains the current client type for clients in the database. Is there a way to show in 'combo' both 'client_type_dropdown.name' and 'clients.client_type' , i.e., one source for the ComboBoxColumn dropdown and a different source for the textbox part of 'combo'? Or do I need to have two columns in my grid?
I appreciate your help.
I'm using a third party grid, but I usually handle this by setting the combo drop down style to DropDown instead of DropDownList. This will allow your original database value to display, even if it isn't in the list.
This also allows free typing of values into the combo field, so the trick after that is to validate the user input to make sure it matches a value in the list before you allow them to save updated values. You could play around with the LimitToList property of the combo to possibly save you doing the validation manually, but with most controls I have worked with it will give you more grief than help.
I'm in C# Express 2010 and SQL Server Express 2008, making a winforms front end for simple table editing. User picks a table from a combobox, and a datagridview is populated with that table. There's a Submit and Reload button at the bottom of the form. It's loosely based on Microsoft's example for binding a DGV to a database.
So, I have this datagridview that is populated by a data adaptor. After it's been populated, I go through the resulting table and replace any columns with foreign keys with comboboxcolumns so it's easier for the user.
This bit all works fine. The comboboxcolumn shows up, with the correct data in it etc etc. I've set the Headertext, DataProprtyName, and Name properties to match the column it has replaced.
It DOES seem to have broken my 'submit' button that does the update command. Basically, if I change the value in one of the comboboxcolumns, I get a concurrency violation. If I change a value in any other column, it silently fails (when the data is reloaded into the DGV, the updated value vanishes).
Any ideas what the problem could be here?
If you need to see code just let me know. There's rather a lot of it as I'm a newbie and have probably done things in a horrendously messy way!
Thanks in advance.
Never mind - I figured it out - I had copy/pasted a procedure and forgotten to create a new DataAdaptor, so it was using the same one as the one used to populate the DGV, hence things went A over T...
I've got kind of a conceptual question. I am in the process of wrapping some statistics classes I wrote into WPF.
For that I have two DataGrid(-Views, currently in WinForms). In one DataGrid each row represents a column in the other. There I can set-up different variables (as in mathematical/statistical variables) with fields like "Header", "DataType", "ValidationBehaviour", "DisplayType". There I can also set-up how it should be displayed. Some Columns can automatically be set to ComboBoxColumns, some TextBoxColumns, and so on and so forth.
So, now once I've set-up these Columns I can go to the other grid and enter my data. I may, for instance, have generated (in grid 1) one Column called "Annual Gross Salary" with input of numerical values. Another Column called "Education" with "0=NoEducation", "1=College Level", "3=Universitary" etc. These labels are displayed as text in the combobox and my statistics engine behind then selects the respective value (0-3) for calculations (i.e. ordinal, nominal variables).
Sooo. In WinForms I could basically generate all the columns by hand in code and then add my data in the respective cells/rows. Now in WPF I thought that must be easy to realise. However, yesterday I got started with ICustomPropertyDescriptor which (maybe I was too thick) didn't give me the results I was looking for.
Basically, I just need to be able to dynamically generate columns (and rows) with different Layout, Controls (ComboBox, simple Input, DateTimes) based on the data that I have. But I don't really know how to go about it?
So here in summary:
DataGrid 1
Purpose is to display columns that have been specified in DataGrid 2
In rows, the user can add any kind of data in the rows below the columns that is allowed as to the columns specifications
DataGrid 2
Each row in this grid represents a column in DataGrid 1
Contains fields like Name/Header, DataType, Validation Behaviour, Default Value, Data Formatting, etc.
Also contains a function to be able to set-up how it should be displayed. The user can select from, for instance, ComboBoxColumn (and also add the available options), DateTime, normal TextBox, CheckBox etc.
After finishing adding a row it will automatically appear as a new column in DataGrid 1
I'd appreciate any kind of pointer into the right direction. Thanks very, very much in advance! :)
Look up DataTemplates. They do exactly this. The UI is determined by the related type.
Here is an MSDN article...
I have a noob question.
I have a WinForm (.net 2.0 in VS 2008) on my form I have a DataGrid. One of the fields in that DataGrid is a combo box that is bound to a separate table. This works, but I am unable to edit or add. I cannot add a value that is not on the list.
I want to create a lookup box (for lack of a better term).
The form is for Parts Order Entry. In the DataGrid Data Source is PartsOrder_table, the Work order Field is an int in the PartsOrder_table, and the combo box is bound to the WorkOrder_table. The WorkOPRder_Table has WorkOrd_ID int and WrkOrd nvarchar(10)
The Combo Box Data Source is WorkOrd_Table Display Member is WorkOrd Value Member is WorkOrder_ID.
This works great with the problem that I cannot add or select anything not in WorkOrder_table.
Any help would be greatly appreciated.
Seems you cannot in a straight forward manner. This thread shows a way of doing this, by adding the needed values during the Validation of the ComboBox control. See the URL for more details.
http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/31a28e99-6f9f-4cce-b256-9b7cf1ddf69a/
I have a table Resource with a field Type. Type is a lookup into the table ResourceType.
So for instance ResourceType might have:
1: Books
2: Candy
3: Both
And Resource might have
1: Tom's Grocery, 2
2: Freds News, 3
It would display as: Tom's Grocery Candy
Now lets say I am using a databound combobox for the resource type and the third record is deleted from ResourceType, we of course get an error when Fred's News is displayed. I could simply put a marker in (perhaps an asterisk), indicating that it has been deleted, rather than actually delete it. It shows up as **Both* in the textbox portion of the combo and I am content.
However, I would not want it to show up as an option in the dropdown. Is this too much to ask from databound fields? Must I write my own code to load the drop down?
Add a bit Deleted column to the lookup table. When you delete a type, set Deleted = 1. When you pull back ResourceTypes, only pull out ResourceTypes where Deleted = 0 and then bind to the dropdown.
Edit:
How are you getting the dataset that you're binding to the dropdownlist? Are you using drag and drop datasets? I really haven't worked with datasets like that in years, but I'm pretty sure you can change the Get sql to what you need it to be.
OK, I already have most of that built into the solution - but I must be binding wrong. If I only pull back records where deleted = 0, I get exceptions - I'm guessing because the textbox can't be filled from the record set.
I guess I'm not sure how to bind the textbox display to one dataset - the one with all the records - and the dropdown to a filtered dataset.
Simply adding a deleted column was not enough - there had to be a way to see a deleted record in the text portion of a combo box while at the same time filtering out deleted records in the drop down.
In the end, I wrote a custom user control to handle this.